数字签名与证书实战:使用OpenSSL亲手实验

数字签名与证书实战:使用OpenSSL亲手实验
XR引言:从理论到实践
在上一篇文档《数字签名与数字证书深度解析》中,我们深入探讨了数字签名与证书背后的密码学原理。但是理论是理论,实际上密钥长什么样,怎么生成、加密以及证书如何生成,还是需要自己去实践。
本篇将我通过终端,使用强大的openssl工具集,亲手模拟和复现数字签名与证书的全过程。你将直观地看到:
- 一个合法的签名如何被验证通过。
- 当文件被篡改或签名被伪造时,验证如何失败。
- 一个权威的CA是如何为他人签发“数字身份证”(证书)的。
一、 准备工作
首先,我们需要一个工作目录和一份用于签名的原始文件。
1 | # 创建一个名为 "openssl_practice" 的工作目录并进入 |
二、 实验一:标准的数字签名与验证
我们将模拟小明生成密钥对,对contract.txt文件签名,然后小红使用其公钥进行验证。
步骤1:生成私钥
小明首先需要一个独一无二的私钥。
命令:
1 | openssl genpkey -algorithm RSA -out xiaoming_private_key.pem |
终端输出:
1 | .....+++++++++++++++++++++++++++++++++++++++*..+...+...+.+......+++++++++++++++++++++++++++++++++++++++*..+..+............+.+.....+.+......+..+.......+.........+............+.....+...+....+..+...............+...+.+....+.............+.....+....+...+.....+...+........................+.+.....+....+.................+......+.......+.......................+.......+...+.....+.........+....+......+.....+.+..+...+.........+.+................+...............+.........+...+.....+...+..................+.+...+...+..+......+.+.....+.+..+.............+....+..+...+....+...+...+...........+............................+............+............+...+......+.....+.+.........+..+.....+...+..........................++++++ |
此时,目录下生成了xiaoming_private_key.pem文件,这就是小明的“数字印章”的根基。
步骤2:提取公钥
小明需要从私钥中提取出公钥,以便分发给其他人(如小红)用来验证。
命令:
1 | openssl pkey -in xiaoming_private_key.pem -pubout -out xiaoming_public_key.pem |
此命令执行后没有复杂的输出,它会静默地生成xiaoming_public_key.pem文件。
步骤3:进行数字签名
小明现在使用他的私钥对合同文件进行签名。这个过程包含计算哈希和用私钥加密哈希两个步骤,openssl会一步完成。
命令:
1 | openssl dgst -sha256 -sign xiaoming_private_key.pem -out contract.sig contract.txt |
执行后,会生成一个contract.sig文件,这就是数字签名。它是一个二进制文件,无法直接阅读。
步骤4:验证数字签名
小明将contract.txt(原文)、contract.sig(签名)、xiaoming_public_key.pem(公钥)三者都交给了小红。小红开始验证。
命令:
1 | openssl dgst -sha256 -verify xiaoming_public_key.pem -signature contract.sig contract.txt |
终端输出:
1 | Verified OK |
Verified OK这个输出明确地告诉我们:验证通过! 小红可以确信,这份文件确实来自小明,并且内容完好无损。
三、 实验二:模拟攻击,观察验证失败
“安全”的最好证明,就是看它在“不安全”的情况下如何反应。
场景1:文件内容被篡改
假设攻击者小黑在传输过程中修改了合同。
命令:
我们将合同内容修改,然后立即用原始签名和小明的公钥进行验证。
1 | # 修改文件内容 |
终端输出:
1 | Verification Failure |
Verification Failure! 验证失败。因为文件内容的哈希值变了,与签名解密后的原始哈希值不匹配。
场景2:签名被伪造
现在,我们将文件恢复原状,但模拟小黑试图用自己的私钥签名,冒充小明。
命令:
1 | # 恢复原始文件 |
终端输出:
1 | Verification failure |
同样Verification Failure!因为小黑的签名只能用小黑的公钥解密。小红用小明的公钥尝试解密,结果自然是失败的。
扩展探讨:验证失败的底层原因
这里可能会有一个疑问:使用错误的公钥进行验证,究竟是在RSA解密时就直接报错了,还是解密出了一段无用的内容?
Verification Failure背后的具体含义是什么?详细拆解如下:
签名的内部结构:为了安全,签名过程并不是只对原始哈希进行加密。而是会先将哈希值包裹在一个有特定格式的“信封”里,这个过程叫做填充(Padding)。一个典型的填充后结构看起来像:
[固定前缀] + [一堆填充字节] + [哈希算法标识] + [原始哈希]。最后,私钥加密的是这个整体。验证时的第一关:当用公钥去“解密”签名时,密码库(如OpenSSL)的第一件事就是检查解密出来的东西是否符合上述预定义的“信封”格式。
错误公钥的后果:由于使用的是与签名私钥不匹配的公钥,解密操作会得到一串完全随机、毫无规律的二进制乱码。
失败的根源:当密码库试图在这串乱码中寻找那个严格的填充格式时,会立刻发现格式对不上。因此,它根本不会继续往后走去提取所谓的“原始哈希”进行比较。流程会直接中断,并抛出一个底层的密码学错误,这正是实验输出中看到的:
bad signature(签名数据本身格式不正确)padding check failed(填充格式检查失败)所以,总结来说:验证过程并不是解密出一个“错误的哈希值”再去比较,而是在解密后的第一时间,就因为无法通过最基本的格式校验而提前失败。 这个“格式校验”是防御各种攻击(如伪造签名)的一道关键防线。
场景3:公钥被掉包(中间人攻击)
这是最隐蔽也最危险的攻击。前两个场景的验证都失败了,保护了我们。但如果小黑从一开始就欺骗了小红,让她误以为小黑的公钥就是小明的公钥呢?
命令:
1 | # 恢复原始文件 |
终端输出:
1 | Verified OK |
Verified OK!验证成功了! 这就是中间人攻击的可怕之处。小红的所有验证步骤都是对的,但因为她信任的“根”——也就是她手中的公钥——从一开始就是错的,整个信任链条就崩溃了。她以为自己验证了小明的签名,实际上验证的是小黑的签名。
这三个实验,特别是最后一个,彻底暴露了单纯数字签名的致命弱点:我们无法通过签名技术本身来保证公钥的真实性。小红无法100%确定她手中的xiaoming_public_key.pem就是小明本人的。 这就是为什么我们需要一个更高级的机制——数字证书——来登场解决公钥的信任问题。
四、 实验三:签发与验证数字证书
现在我们升级角色,扮演一个根证书颁发机构(Root CA),为小明签发一份可信的证书。
步骤1:CA生成自己的根密钥对
这是信任的源头。
命令:
1 | openssl genpkey -algorithm RSA -out root_ca_private_key.pem |
步骤2:CA生成自签名根证书
CA用自己的私钥给自己签名,制作一张“顶级身份证”。这张证书未来将被内置到操作系统和浏览器中。
命令:
1 | openssl req -x509 -new -nodes -key root_ca_private_key.pem -sha256 -days 3650 -out root_ca.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=My Root CA/CN=my-ca.com" |
我们创建了一个有效期10年的根证书root_ca.crt。
步骤3:小明创建证书签名请求(CSR)
小明需要向CA申请证书。他要先生成自己的新密钥对,然后创建一个包含其公钥和身份信息的CSR文件。
命令:
1 | # 小明为申请证书生成新的密钥对 |
步骤4:CA签署小明的CSR,颁发证书
CA收到小明的xiaoming.csr后,进行审核。审核通过后,用自己的根私钥对其进行签名,正式生成小明的数字证书。
命令:
1 | openssl x509 -req -in xiaoming.csr -CA root_ca.crt -CAkey root_ca_private_key.pem -CAcreateserial -out xiaoming_site.crt -days 365 -sha256 |
终端输出:
1 | Certificate request self-signature ok |
现在,xiaoming_site.crt就是小明的官方“数字身份证”了。
步骤5:验证小明的证书
小红拿到了xiaoming_site.crt。她要用她电脑里预装的、信任的root_ca.crt来验证这张“身份证”的真伪。
命令:
1 | openssl verify -CAfile root_ca.crt xiaoming_site.crt |
终端输出:
1 | xiaoming_site.crt: OK |
**OK!**验证通过。这表明小红可以完全信任xiaoming_site.crt中的公钥确实属于CN=xiaoming-site.com。
步骤6:查看证书内容
我们可以像看身份证一样,查看证书里的详细信息。
命令:
1 | openssl x509 -in xiaoming_site.crt -noout -text |
终端输出:
1 | Certificate: |
从输出中,我们可以清晰地看到**颁发者(Issuer)是我们的CA,主题(Subject)**是小明,以及证书中包含的小明的公钥。
结论
通过这一系列动手实验,我们不仅验证了理论,更获得了直观的体感。现在,当你看到浏览器地址栏那把“安全锁”时,你脑海将回是一整套由openssl命令模拟出的、严谨的、环环相扣的签名、签发与验证流程。
数字签名与证书,不仅应用于网络信任体系。在计算机其他方方面面都有广泛应用。我写本篇的契机也是在研究SGX、HyperEnclave时,为之前不够深入理解签名与证书进行补课。












