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 0x000000000000000。當發生這種情況時,接收者確實嘗試使用他們擁有的所有具有秘密加密功能的子金鑰透過暴力方式解密資料包。

還有一個--hidden-recipient選項允許以相同的方式隱藏各個收件人,因此您可以在結果訊息中混合使用空和非空密鑰 ID。這對於Bcc:在電子郵件用戶端中實現副本可能很有用。

當您需要透過公共公告板/投遞箱/Reddit 子版塊等方式交換訊息並且不想透露預期收件人時,可以使用這兩個選項。

$ 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:
...

相關內容