PGP ключи в виде QR-кодов
Если хочется сделать hard copy ключа PGP/GPG (что в общем случае может быть хорошей идеей, не забываем про мантру делайбэкапыкаждыйдень), но перспектива при необходимости вбивать посимвольно или возиться с OCR не воодушевляет, на помощь приходят неожиданно QR-коды.
Генерировать QR можно, например, небольшой консольной утилитой qrencode
. Прочитать QR кроме телефона можно например утилитой zbar
. Это не очень интересно. Интереснее оказывается вопрос как закодировать ключ в QR наиболее эффективным образом.
В принципе, для эллиптических ключей, просто экспорт через gpg --armor
даст умеренно сносные результаты, i.e. результат уместится в один QR-код. А ключи RSA вменяемой длины (2048-4096), как их ни сжимай, на один QR-код не влезут.
Тем не менее, эксперименты показали, что двоичное представление ключа (т.е. без --armor
), ужатое либо lzma
либо zstd
и преобразованное в base32 даёт наилучшие результаты. Base32 потому что QR-коды наиболее оптимально кодируют латинские буквы без учёта регистра и цифры, поэтому base64 оказывается в итоге дороже, несмотря на то что сам текст короче.
Не буду больше тянуть, однострочник такой:
gpg --export-secret-keys <keyid> | lzma | base32 | qrencode -o- -lH -tEPS | lpr
Можно указать несколько ключей, если понизить избыточность (параметр -lL
вместо -lH
), можно уместить по крайней мере 5 эллиптических ключей на один QR. Но мне несколько претит понижать избыточность без крайней нужды, бумага – не слишком надёжный носитель.
Понятно, это работает для эллиптических ключей, потому что они короткие. Для длинных – можно использовать т.н. structured QR, т.е. размазывание данных по нескольким QR-кодам. Однострочник тогда примет вид:
gpg --export-secret-keys <keyid> | lzma | base32 | qrencode -ooutput.eps -lH -tEPS -S -v40
Эта команда создаст несколько файлов вида output-nn.eps
, где nn
это номер.
Ключ -S
включает structured QR, -v40
устанавливает максимальный размер для каждого индивидуального QR-кода. С высокой степенью избыточности (-lH
) можно уместить 4096-битный ключ на 7 QR-кодах (каждый размером с лист A4), а с низкой (-lL
) – “всего” на 3-х.
Нюанс в том, что structured QR не так-то просто прочитать обратно. Мне это удалось только отсканировав распечатки, склеив их в один файл в правильном порядке и скормив это в zbarimg
. Отдельно отмечу, что фотографии на камеру телефона оказались недостаточно чёткими, чтобы их потом прочитать (по крайней мере с -lL
).
Альтернативные варианты для больших ключей:
- Кодировать в формат datamatrix вместо QR, например используя dmtx-utils
- Использовать paperkey чтобы удалить “несекретные” части секретного ключа. Публичный ключ тогда должен быть доступен по каким-то другим каналам, например загружен на серверы ключей и т.п.
Более подробно эти альтернативы рассмотрены, например здесь
Ну и в заключение, я эту технику применил чтобы сделать hard copy, но в общем случае можно аналогичный подход использовать для обмена публичными ключами офлайн – эллиптические публичные ключи тоже достаточно короткие. На правах proof of concept: