Как использовать GnuPG для получения наименьшего возможного результата (симметричное шифрование)?

690
Daan Bakker

Я пытаюсь создать очень маленькие зашифрованные OpenPGP файлы, которые можно встраивать в QR-коды.

Однако, по сравнению, например, с OpenSSL, GnuPG, кажется, дает очень большие результаты для простого ввода 'a':

$ echo -n a|openssl enc -aes-256-ctr|wc -c  17 $ echo -n a|gpg --symmetric -o-|wc -c 71 

Из прочтения руководства одно из отличий заключается в том, что OpenSSL по умолчанию включает только 8-байтовый заголовок и 8-байтовую соль, а GnuPG также включает в себя соль, контрольные суммы и сжатие. Если они отключены, размер файла меньше, но все еще высок:

$ echo -n a|gpg --symmetric --compress-algo none --disable-mdc --s2k-mode 0 -o-|wc -c 35 

Есть ли способ еще больше оптимизировать зашифрованное сообщение OpenPGP (при этом AES будет включен)?

5

1 ответ на вопрос

6
Jens Erat

Хотя двоичный формат 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 не делает этого, но вы не можете пропустить это, если не предоставите ключ сеанса вместо ключевой фразы, не предоставив ключ сеанса отдельно (обсуждается ниже). Этот пакет имеет шесть байт и состоит из:

# 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- который, конечно, экономит несколько байтов для зашифрованной контрольной суммы файла. Вы можете попробовать самостоятельно, изменив последний байт в шестнадцатеричном редакторе.

Похожие вопросы