Я недавно боролся с GPG, и только что (наконец-то!) заставил его работать. Теперь я могу ввести зашифрованный blob в gpg.exe, и он выведет версию в виде открытого текста, предполагая, конечно, что это допустимый blob шифрования, то есть его ключ дешифрования есть в моем списке закрытых ключей/"криптоидентификаторов".
Мой вопрос: как именно GPG определяет, какой из этих ключей пробовать? Эта информация каким-то образом зашита в криптографический блок? Или он просто слепо пробует их, один за другим, пока один из них не расшифрует его?
Было бы неплохо наконец получить ответ на этот вопрос, потому что я думал об этом уже много лет. Это кажется таким «грубым» и «низкотехнологичным», чтобы просто пройтись по ним всем. Особенно, если, например, я начну размещать какой-то сервис, где тысячи личных ключей людей должны пройти, чтобы проверить, совпадает ли новое входящее сообщение с каким-либо из них. Это просто не «масштабируется».
Я очень надеюсь, что в зашифрованном тексте есть что-то, что подскажет GPG, какой ключ пробовать! Так ли это?
решение1
Полученный пакет OpenPGP действительно содержитидентификатор подключаемого ключа шифрованияполучателя, который должен иметь возможность его расшифровать. Например:
$ 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, планируется использовать полные отпечатки подключей. Однако в этой ситуации укороченные идентификаторы ключей вполне подходят.)
При этом у GnuPG есть опция под названием --throw-keyids
, которая заставляет все пакеты сессионных ключей иметь одинаковый идентификатор ключа 0x00000000000000000. Когда это происходит, получатель действительно пытается расшифровать пакет методом подбора, используя все секретные подключи, поддерживающие шифрование, которые у него есть.
Также есть --hidden-recipient
опция, которая позволяет скрывать отдельных получателей таким же образом, так что вы можете иметь смесь нулевых и ненулевых идентификаторов ключей в результирующем сообщении. Это может быть полезно для внедрения Bcc:
копий в почтовых клиентах.
Оба варианта можно использовать, когда вам нужно обмениваться сообщениями через что-то вроде публичной доски объявлений/дропбокса/сабреддита и вы не хотите раскрывать предполагаемого получателя.
$ 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:
...