假设你使用 GPG 验证某人的签名:
$ gpg --decrypt statement.txt.sig
"I am not a crook."
gpg: Signature made 17 Nov 1973 9:31:50 AM CDT using RSA key ID 92861D99
gpg: Good signature from "Richard Nixon <[email protected]>"
gpg: aka "[jpeg image of size 19022]"
该statement.txt.sig
文件显然包含已签名的声明/数据以及签名者的公钥。然而,更多信息输出中包含的信息,例如全名和电子邮件地址,以及包含签名者公钥的 JPEG 图像。
GPG 从哪里获取这些额外的数据?它是否包含在文件中statement.txt.sig
,还是查看您的钥匙圈并“填写”您掌握的有关此人的所有额外详细信息?
答案1
不,信息来自保存在公钥环中的证书(或从密钥服务器下载)。签名仅包含查找正确证书所需的一些信息。
使用gpg --list-packets
或pgpdump
:
$ echo Foo。> foo.txt $ gpg --detach-sign foo.txt $ gpg --list-packets < foo.txt.sig :签名包:算法1,密钥 ID D24F6CB2C1B52632 版本 4,创建于 1410762670,md5len 0,sigclass 0x00 摘要算法 10,摘要开始 25 58 散列子包 2 长度 4 (签名创建于 2014-09-15) subpkt 16 len 8(发行者密钥 ID D24F6CB2C1B52632) 数据:[4091位]
分离签名有一个“签名”包,其中包含算法、签名时间戳和签名者的 8 字节密钥 ID,用于在您的密钥环中查找签名者的证书。(如果您没有具有该密钥 ID 的任何公钥,GnuPG 将尝试在公共密钥服务器中查找一个。)
(我不知道为什么它有两次密钥ID。)
GnuPG 通过查找 keyid 获取有关签名者的所有信息– 公钥实际上验证签名,以及用于描述签名者的用户 ID 字段(姓名、地址、照片)。
另外:请注意,您的示例有一个较短的 4 字节密钥 ID,这非常糟糕,因为已知有数百个短密钥 ID 冲突,既有故意的也有意外的。keyid-format long
在您的 ~/.gnupg/gnupg.conf 中使用会使其显示较长的密钥 ID,尽管这些密钥 ID 仍然很容易故意发生冲突,因此您应该总是导入新密钥时检查指纹。
(但是,签名包中始终保留一个 8 字节的密钥 ID。有些人将 GnuPG 配置为将指纹放在自定义字段(符号)中,但不幸的是,软件本身并不使用它。)
回到签名。如果你gpg --list-packets
对常规(内联)签名进行操作,你会看到更多内容:
:压缩包:算法=1 :onepass_sig 数据包:密钥 ID D24F6CB2C1B52632 版本 3、sigclass 0x00、摘要 10、公钥 1、最后=1 :文字数据包: 模式 b (62),创建于 1410762587,名称="", 原始数据:5个字节 :签名包:算法1,密钥ID D24F6CB2C1B52632 版本 4,创建于 1410762587,md5len 0,sigclass 0x00 摘要算法 10,摘要 eb 31 的开始 散列子包 2 长度 4 (签名创建于 2014-09-15) subpkt 16 len 8(发行者密钥 ID D24F6CB2C1B52632) 数据:[4095位]
实际签名的消息位于“文字数据”包中,通常使用 DEFLATE 压缩(pgpdump
将显示正在使用的实际算法)。
它前面有一个“onepass_sig”数据包,其唯一目的是提供密钥 ID,而不必读完整个消息 - 因此 GnuPG 可以立即开始搜索密钥 ID 并继续验证消息。(当从管道读取时,例如cat|gpg
,不可能向前和向后搜索;所有内容必须一次性读取。)
如果需要,您也可以使用签名者的密钥(证书)执行此操作。只需先将其导出到文件即可:
# gpg --export D24F6CB2C1B52632 | gpg --list-packets :公钥包: 版本 4,算法 1,创建日期 1256993643,到期日期 0 pkey[0]: [4096位] pkey[1]: [17位] 密钥ID:D24F6CB2C1B52632 :用户 ID 包:“Mantas Mikul\xc4\x97nas” :签名包:算法1,密钥ID D24F6CB2C1B52632 版本 4,创建 1256993643,md5len 0,sigclass 0x13 摘要算法 10,摘要 5a e2 的开始 [更多台词]
证书也由一些数据包组成,首先是公钥,然后是用户 ID(文本标签),每个用户 ID 都有一个自签名(以防止有人将假用户 ID 附加到公钥),然后是几个公共子密钥数据包(同样带有自签名)。