介绍
欢迎来到关于 RSA 数字签名的实验。数字签名是一种加密机制,用于验证数字消息或文档的真实性和完整性。它确保消息由已知的发送者创建(真实性),并且在传输过程中未被篡改(完整性)。
在这个实验中,你将获得关于数字签名整个生命周期的实践经验。我们将使用 openssl 命令行工具,这是一个强大且多功能的加密任务工具。你将学习如何使用私钥生成签名,以及如何使用相应的公钥验证签名。最后,你将对数字签名如何保护我们的数字通信有一个实际的理解。
数字签名概念
在这一步,我们将开始理解数字签名的核心概念。数字签名是由发送方使用其 私钥 (private key) 创建的。这个密钥是保密的,只有发送方知道。然后,任何拥有发送方相应 公钥 (public key) 的人都可以验证该签名。
这个过程提供了两个关键的安全保证:
- **真实性 (Authenticity)**:由于只有发送方拥有私钥,一个有效的签名证明了消息确实来源于他们。
- **完整性 (Integrity)**:签名在数学上与消息的内容相关联。如果消息以任何方式被更改,签名将不再有效。
为了方便本次实验,设置过程已经为你生成了一对 RSA 密钥对:private.pem(你的密钥)和 public.pem(你可以分享的密钥)。它还创建了一个名为 message.txt 的文件。让我们列出项目目录中的文件来看看它们。
在你的终端中执行以下命令:
ls -l
你应该会看到为你准备好的文件:
-rw-rw-r-- 1 labex labex 55 Oct 20 09:20 document.txt
-rw-rw-r-- 1 labex labex 26 Oct 20 09:20 message.txt
-rw------- 1 labex labex 1704 Oct 20 09:20 private.pem
-rw-rw-r-- 1 labex labex 451 Oct 20 09:20 public.pem
现在我们有了密钥和消息,我们准备创建我们的第一个数字签名。
使用私钥签名消息
在这一步,你将为 message.txt 文件创建一个数字签名。这个过程涉及两个主要操作:首先,创建消息的加密哈希(一个唯一的固定大小的字节字符串),然后,使用你的私钥加密该哈希。结果就是数字签名。
我们将使用 openssl dgst 命令来执行此操作。让我们运行命令来签名 message.txt。
openssl dgst -sha256 -sign private.pem -out signature.bin message.txt
我们来分解一下这个命令:
openssl dgst: 这会调用 OpenSSL 的摘要 (digest) 命令。-sha256: 这指定使用 SHA-256 算法来创建消息哈希。-sign private.pem: 这告诉 OpenSSL 使用指定的私钥private.pem来签名哈希。-out signature.bin: 这指定了结果二进制签名将被存储的输出文件。message.txt: 这是我们要签名的输入文件。
运行该命令后,会创建一个名为 signature.bin 的新文件。该文件包含数字签名。你可以通过再次列出文件来验证它的创建。
ls -l
你现在将在文件列表中看到 signature.bin:
-rw-rw-r-- 1 labex labex 55 Oct 20 09:20 document.txt
-rw-rw-r-- 1 labex labex 26 Oct 20 09:20 message.txt
-rw------- 1 labex labex 1704 Oct 20 09:20 private.pem
-rw-rw-r-- 1 labex labex 451 Oct 20 09:20 public.pem
-rw-rw-r-- 1 labex labex 256 Oct 20 09:26 signature.bin
使用公钥验证签名
在这一步,我们将扮演一个想要验证签名的接收者的角色。要做到这一点,接收者需要三样东西:原始消息 (message.txt)、数字签名 (signature.bin),以及发送方的公钥 (public.pem)。
验证过程与签名过程相反。OpenSSL 将使用公钥解密签名,从而揭示原始哈希。然后,它将独立计算收到的消息的新哈希。如果两个哈希匹配,则签名有效。
让我们再次使用 openssl dgst,但这次使用 -verify 选项。
openssl dgst -sha256 -verify public.pem -signature signature.bin message.txt
以下是验证命令的分解:
-verify public.pem: 这告诉 OpenSSL 使用指定的公钥public.pem来验证签名。-signature signature.bin: 这指定了要验证的签名文件。message.txt: 这是签名应该对应的原始消息文件。
如果签名有效,OpenSSL 将输出以下消息:
Verified OK
这个确认意味着两件事:消息确实是由 private.pem 密钥的所有者签名的,并且自签名以来 message.txt 的内容没有被更改。
使用私钥对文件签名
在这一步,我们将通过将签名应用于另一个文件来加强签名过程。这将有助于巩固你对如何创建和使用签名哈希的理解。我们的目录中还有一个名为 document.txt 的文件。我们现在将为该文档创建一个数字签名。
该过程与我们在步骤 2 中所做的完全相同。我们将生成 document.txt 的 SHA-256 哈希,然后使用我们的 private.pem 密钥对该哈希进行签名。
让我们创建签名并将其保存到名为 document.sig 的文件中。
openssl dgst -sha256 -sign private.pem -out document.sig document.txt
此命令会创建一个新的签名文件 document.sig,它特定于 document.txt 的当前内容。文档的任何更改都需要生成一个新的签名。
让我们列出文件以确认 document.sig 已创建。
ls
你应该在输出中看到新的签名文件:
document.sig document.txt message.txt private.pem public.pem signature.bin
现在我们有了一个已签名的文档,我们将在下一步中使用它来演示数字签名的完整性检查能力。
测试签名篡改
在最后一步中,我们将演示数字签名最关键的特性:完整性保护。我们将故意篡改 document.txt 文件(在其被签名之后),然后尝试使用原始签名对其进行验证。这将展示数字签名如何防止未经授权的修改。
首先,让我们向 document.txt 文件中添加一些文本。这模拟了攻击者更改文档的行为。
echo "This is an unauthorized change." >> document.txt
现在 document.txt 的内容已更改。原始签名 document.sig 是基于文件先前的内容创建的。
现在,让我们尝试使用原始签名 document.sig 和公钥来验证已修改的 document.txt 文件。
openssl dgst -sha256 -verify public.pem -signature document.sig document.txt
这一次,验证将不会成功。相反,你会看到类似以下的错误消息:
Verification failure
805BA484597F0000:error:02000068:rsa routines:ossl_rsa_verify:bad signature:../crypto/rsa/rsa_sign.c:430:
805BA484597F0000:error:1C880004:Provider routines:rsa_verify:RSA lib:../providers/implementations/signature/rsa_sig.c:774:
这种失败是预期的结果。发生这种情况是因为修改后的 document.txt 的哈希值不再与加密在 document.sig 中的哈希值匹配。这立即证明了文件自签名以来已被篡改。这种机制对于信任数字文档和通信是至关重要的。
总结
在这个实验中,你已成功学习了使用 RSA 和 OpenSSL 进行数字签名的实际应用。
你已经走完了整个过程:
- 理解了数字签名提供的真实性(authenticity)和完整性(integrity)的核心概念。
- 使用私钥 (
private.pem) 对消息进行签名并创建签名文件。 - 使用相应的公钥 (
public.pem) 来验证签名并确认消息的真实性。 - 在故意篡改已签名文件后,目睹了
Verification failure(验证失败),证明了数字签名如何保护数据完整性。
这种实践经验为你理解数字世界中信任是如何建立的奠定了坚实的基础,这是网络安全和现代计算中的一个关键概念。



