Хотя двоичный формат GnuPG довольно компактен, он создан для гибкости, а не для абсолютно минимальных размеров сообщений (обычно реальное сообщение намного больше, чем несколько байтов). Минимальное «обычное» сообщение OpenPGP имеет размер 31 байт, но вы все равно можете сократить его до 26 байт с некоторыми дополнительными усилиями, что является наименьшим возможным сообщением OpenPGP v4 для однобайтового содержимого.
Рассеивание сообщения OpenPGP, подсчет байтов
Взглянув на RFC 4880, вы можете получить минимальную длину сообщения, которую вы не можете использовать ниже.
Давайте посмотрим на вывод команды, которую вы создали:
$ echo -n a|gpg --symmetric --compress-algo none --disable-mdc --s2k-mode 0 -o-|gpg --list-packets gpg: Note: simple S2K mode (0) is strongly discouraged gpg: AES encrypted data gpg: encrypted with 1 passphrase gpg: WARNING: message was not integrity protected
Первый пакет является зашифрованным сессионным ключом пакета сеансового ключа . Он содержит копию ключа сеанса, зашифрованную парольной фразой с использованием механизма «строка-к-ключу». OpenSSL не делает этого, но вы не можете пропустить это, если не предоставите ключ сеанса вместо ключевой фразы, не предоставив ключ сеанса отдельно (обсуждается ниже). Этот пакет имеет шесть байт и состоит из:
- 2-байтовый заголовок пакета (тег и длина)
- 1-байтовый номер версии
- 1-байтовый симметричный идентификатор алгоритма
- 2-байтовый спецификатор s2k (1-байтовый «простой режим s2k», 1-байтовый алгоритм хеш-функции)
# off=0 ctb=8c tag=3 hlen=2 plen=4 :symkey enc packet: version 4, cipher 7, s2k 0, hash 10
Теперь зашифрованные пакеты данных запускаются. Это содержит:
- 2-байтовый заголовок пакета (тег и длина)
- Случайный префикс в 18 байт (вместо 0-байтового IV CFP OpenPGP использует случайный префикс в размере блока шифра и повторяет первые два байта; AES использует 128 бит = 16 байтов в качестве длины блока шифра)
# off=6 ctb=c9 tag=9 hlen=2 plen=26 new-ctb :encrypted data packet: length: 26
OpenPGP всегда сохраняет сообщение в буквальном пакете данных, который добавляет некоторые метаданные. Отключение сжатия, по крайней мере, удаляет дополнительные заголовки сжатия. Этот пакет наконец добавляет еще 9 байтов:
- 2-байтовый заголовок пакета (тег и длина)
- 1-байтовый формат данных
- Длина строки имени файла в 1 байт (значение ноль, имя файла не следует)
- Метка времени 4 байта
- 1 байт
# off=26 ctb=cb tag=11 hlen=2 plen=6 new-ctb :literal data packet: mode b (62), created 1503680075, name="", raw data: 0 bytes
Подводя итог: вы не сможете сохранить еще один байт - если не пропустите вывод строки в ключ и напрямую используете ключ сеанса вместо ключевой фразы.
Пропуск функции "строка-к-ключу"
GnuPG позволяет читать и устанавливать ключ сессии, используя --show-session-key
и --override-session-key
. Читая главу о создании сообщений, я был удивлен, что действительные сообщения OpenPGP вообще не требуют пакетов, определяющих шифрование сеансового ключа. GnuPG действительно поддерживает этот вид операций, но я бы не стал ставить ставку на другие реализации, так как это очень эзотерический способ использования OpenPGP.
OpenPGP Message :- Encrypted Message | Signed Message | Compressed Message | Literal Message. Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data. Encrypted Data :- Symmetrically Encrypted Data Packet | Symmetrically Encrypted Integrity Protected Data Packet
Это должно сохранить 6 байтов пакета сеансового ключа с зашифрованным симметричным ключом.
Создание сообщения OpenPGP без пакета ключа сеанса с зашифрованным симметричным ключом
Я не нашел способа заставить GnuPG использовать предопределенный сеансовый ключ. Но вы можете сгенерировать симметрично зашифрованное сообщение, извлечь ключ сеанса во время дешифрования, а затем разделить сообщение.
Шифрование сообщения:
$ echo -n a|gpg --symmetric --compress-algo none --disable-mdc --s2k-mode 0 -o message.gpg
Извлечение сеансового ключа (запросит пароль):
$ gpg --show-session-key 0 --decrypt message.gpg gpg: AES encrypted data gpg: encrypted with 1 passphrase gpg: session key: '7:F7FBBA6E0636F890E56FBBF3283E524C' agpg: WARNING: message was not integrity protected
Разделите сообщение OpenPGP на отдельные пакеты:
$ gpgsplit message.gpg
Папка теперь содержит четыре файла: зашифрованный message.gpg
, незашифрованный message
, зашифрованный сессионный ключ сессионного ключа 000001-003.sym_enc
и, наконец, зашифрованный пакет данных 000002-009.encrypted
.
$ ls -l total 16 -rw-r--r-- 1 jenserat jenserat 6 Aug 25 19:36 000001-003.sym_enc -rw-r--r-- 1 jenserat jenserat 29 Aug 25 19:36 000002-009.encrypted -rw-r--r-- 1 jenserat jenserat 1 Aug 25 19:04 message -rw-r--r-- 1 jenserat jenserat 35 Aug 25 19:33 message.gpg
Вы также можете cat
объединить отдельные файлы пакета, чтобы получить обратно message.gpg
- эти два файла просто разделены на части message.gpg
. Обратите внимание на размеры файлов, которые точно соответствуют размерам, рассмотренным выше (хотя, конечно, размер буквального пакета данных содержится в зашифрованном пакете данных, поскольку gpgsplit
не знает парольную фразу)!
Расшифровка отдельного зашифрованного пакета данных
Этот шаг довольно прост:
$ gpg --override-session-key '7:F7FBBA6E0636F890E56FBBF3283E524C' --decrypt 000002-009.encrypted agpg: WARNING: message was not integrity protected
Не забывайте a
перед предупреждением, которое является выходом.
Значение предупреждающих сообщений
GnuPG напечатал два предупреждающих сообщения.
gpg: Примечание: простой режим S2K (0) настоятельно не рекомендуется
Это связано с тем, что простой режим S2K делает атаки методом «грубой силы» и «словарь» на парольную фразу дешевыми и легкими, поскольку он не использует хеширование и соль
Последнее, конечно, позволяет использовать один и тот же ключ сеанса для нескольких файлов, зашифрованных с использованием одной и той же парольной фразы, но помните о последствиях.
gpg: ПРЕДУПРЕЖДЕНИЕ: сообщение не защищено целостностью
Это предупреждающее сообщение говорит о том, что злоумышленник мог изменить это сообщение, если бы расшифровывающая сторона не могла знать об этом факте. Это из-за --disable-mdc
- который, конечно, экономит несколько байтов для зашифрованной контрольной суммы файла. Вы можете попробовать самостоятельно, изменив последний байт в шестнадцатеричном редакторе.