GPG 如何在内部确定使用哪个密钥来解密给定的输入加密 blob?

GPG 如何在内部确定使用哪个密钥来解密给定的输入加密 blob?

最近我一直在研究 GPG,现在我终于让它工作了。我现在可以将加密的 blob 输入到 gpg.exe,它将输出纯文本版本,当然前提是它是一个有效的加密 blob,这意味着它的解密密钥在我的私钥/“加密标识”列表中。

我的问题是:GPG 究竟是如何确定要尝试其中哪个密钥的?这些信息是否以某种方式嵌入到了加密 blob 中?还是它只是盲目地逐个尝试,直到成功解密?

如果这个问题终于得到解答那就太好了,因为我一直在思考这个问题。如果只是这样检查所有信息,感觉太“粗暴”和“低技术”了。特别是如果我开始提供某种服务,成千上万的人的私钥必须通过,才能确定新收到的消息是否与其中任何一个匹配。这似乎无法“扩展”。

我真的希望加密文本中有一些线索,可以提示 GPG 应该尝试哪个密钥!是这样吗?

答案1

生成的 OpenPGP 数据包确实包含加密子密钥 ID收件人应该能够解密。例如:

$ date | gpg --encrypt | pgpdump
Old: Public-Key Encrypted Session Key Packet(tag 1)(524 bytes)
    New version(3)
    Key ID - 0xCE7B0F19551034EF
    Pub alg - RSA Encrypt or Sign(pub 1)
    ...
New: Symmetrically Encrypted and MDC Packet(tag 18)(83 bytes)
    ...

如果有多个接收者,那么就会有多个“会话密钥”数据包——每个接收者一个,所有数据包都持有同一对称密钥的不同加密版本。

(我认为规范的下一个版本 v5 计划改用完整的子密钥指纹。但是,在这种情况下,截断的密钥 ID 就足够了。)


话虽如此,GnuPG 确实有一个名为的选项--throw-keyids,它会导致所有会话密钥数据包具有相同的密钥 ID 0x00000000000000000。当发生这种情况时,接收者确实会尝试使用他们拥有的所有秘密加密子密钥通过暴力方式解密数据包。

还有一个--hidden-recipient选项允许以同样的方式隐藏单个收件人,因此您可以在结果消息中混合使用空和非空密钥 ID。这可能有助于Bcc:在电子邮件客户端中实现抄送。

当您需要通过公共公告板/投递箱/subreddit 之类的东西交换消息并且不想透露预期收件人时,可以使用这两个选项。

$ date | gpg -e --recipient Alice --hidden-recipient Robert | gpg --list-packets
gpg: anonymous recipient; trying secret key CE7B0F19551034EF ...
gpg: anonymous recipient; trying secret key DCDBB36BD91759A3 ...
gpg: okay, we are the anonymous recipient.
gpg: encrypted with 4096-bit RSA key, ID CE7B0F19551034EF, created 2009-10-31
gpg: encrypted with RSA key, ID 0000000000000000
# off=0 ctb=85 tag=1 hlen=3 plen=524
:pubkey enc packet: version 3, algo 1, keyid 0000000000000000
    data: [4095 bits]
# off=527 ctb=85 tag=1 hlen=3 plen=524
:pubkey enc packet: version 3, algo 1, keyid CE7B0F19551034EF
    data: [4092 bits]
# off=1054 ctb=d2 tag=18 hlen=2 plen=80 new-ctb
:encrypted data packet:
...

相关内容