Expertus metuit
Разбираемся в GnuPG
Опубликовано 2013-03-06 в 15:14

Введение

Здесь написано о GnuPG, как им пользоваться и при этом понимать, что делаешь. Изначально статья была написана в 2013 году, несколько раз слегка обновлялась, а в 2023 была значительно переработана и дополнена актуальной информацией.

GnuPG (GNU Privacy Guard, официальный сайт gnupg.org) — это опенсорсная реализация открытого стандарта OpenPGP, изложенного в RFC 4880. GnuPG состоит из набора программ и библиотек, однако нас будет интересовать только консольная программа gpg. Она существует под все операционные системы, однако наиболее комфортно используется в linux и macos. По gnupg есть множество материалов, однако из-за высокой сложности базовых концептов, всегда есть что добавить или объяснить.

В линуксах gnupg ставится из штатного репозитория, для макоси можно поставить из macports, brew, но я рекомендую GPG Suite. Все эти способы предоставляют вам консольную программу gpg с одинаковыми командами на всех операционках. Текущая актуальная версия GnuPG 2.2 и вся статья отталкивается именно от неё. Многие команды в принципе применимы и для более старых версий.

Между разными версиями gnupg формат хранения данных в каталоге с конфигурацией несколько раз менялся и связанные с этим термины типа keyring уже во многом устарели, поэтому в обновлённой версии я постараюсь не углубляться в конкретные детали реализации и слова типа keyring/кейринг тут использоваться не будут. Чтобы подчеркнуть относительность конфигурации, я буду использовать слово конфиг, под которым вы должны понимать выбранный каталог с конфигурацией. Также я не буду вдаваться в эзотерические команды или свойства подписей, который никем нигде не используются.

Когда я рассказываю о концепциях, то обычно использую термин OpenPGP, когда рассказываю о конкретных прикладных командах, то использую gpg или gnupg.

Пространство для экспериментов

Все свои данные GnuPG хранит в отдельном каталоге, по умолчанию это ~/.gnupg/, однако для экспериментов лучше создать новый пустой, чтобы не потерять данные из главного (если он у вас есть). Пусть это будет ~/gnupg-test/, а для удобства вот команда в shell для создания алиаса (псевдонима):

$ alias gpg="/usr/bin/gpg --homedir=~/gnupg-test"

Теперь вы можете выполнять все описанные ниже команды и не бояться, что они затронут главный каталог. Если у вас macos, то вместо /usr/bin/gpg укажите свой путь, его можно узнать через команду whereis gpg.

И команда для удаления алиаса:

$ unalias gpg

Всё и сразу

Короткая выжимка основных операций. Подробности в разделах ниже. Каждая команда дана в двух эквивалентных вариантах: с короткими и длинными аргументами.

Шифруем файл GPL.txt открытым ключом (моим), результат записывается в GPL.txt.gpg:

$ gpg -e -r [email protected] GPL.txt
$ gpg --encrypt --recipient [email protected] GPL.txt

Расшифровываем присланный файл и записываем результат в файл GPL.txt:

$ gpg -o GPL.txt -d GPL.txt.gpg
$ gpg --output GPL.txt --decrypt GPL.txt.gpg

Создаём цифровую подпись (т.е. подписываем) файл GPL.txt, подпись создаётся в отдельном файле GPL.txt.sig (т.н. отсоединённая подпись, detached signature), в аргументе -u [email protected] указываем, какой ключ использовать:

$ gpg -u [email protected] --detach-sign GPL.txt

Вместо --detach-sign можно писать -b:

$ gpg -u [email protected] -b GPL.txt

Ещё можно сделать цифровую подпись вместе с самим документом, это делается такой командой (подпись записывается в файл GPL.txt.gpg):

$ gpg -u sergei -s GPL.txt
$ gpg --local-user sergei --sign GPL.txt

Полученный на прошлом шаге файл GPL.txt.gpg вместе с подписью содержит и сам документ, его можно извлечь такой командой:

$ gpg --output GPL.txt --decrypt GPL.txt.gpg

А чтобы просто проверить подпись документа, делаем так (это внешняя подпись, поэтому для корректной проверки рядом должен лежать файл GPL.txt):

$ gpg --verify GPL.txt.sig 

Если сам файл для проверки именуется по-другому, можно просто указать его имя в команде:

$ gpg --verify GPL.txt.sig lincense.txt

Идеология и концепты OpenPGP

Концептуально OpenPGP представляет собой крайне сложную для понимания систему понятий и действий. Поскольку OpenPGP не навязывает какой-либо конкретный сценарий использования, его конкретные реализации очень легко можно использовать небезопасно. И даже если вы понимаете все концепты, то даже в такой ситуации не застрахованы от ошибки из-за большой гибкости инструментов.

При использовании gnupg буквально заваливает вас тоннами различных предупреждений и сообщений, степень важности которых неочевидна. И наоборот, в критичных ситуациях нет сообщений, предупреждающих о небезопасности действия. Пример последнего — расшифровка файла без дополнительной подписи.

Продвигаемая в OpenPGP система доверия Web of trust является более гибкой, чем традиционная PKI (public key infrastructure) с делегированием проверки на удостоверяющие центры в TLS, например. Однако эта гибкость даётся ценой очень высокой концептуальной сложности и требованием тщательного изучения концептов. В результате идеи и реализации OpenPGP широкого распространения не получили даже в корпоративной среде, где, в теории, такой подход был бы очень полезен.

Ключи

Главный компонент OpenPGP — ключ. В рабочей конфигурации обычно хранится несколько ключей: ваш собственный и чужие ключи. Каждый ключ состоит из двух частей: обязательной открытой и опциональной закрытой. Закрытая хранится только у владельца ключа в зашифрованном виде. Открытая распространяется свободно в интернете.

закрытая часть используется для:

  • подписывания/удостоверения данных;
  • дешифрования зашифрованных файлов.

Закрытый ключ зашифрован симметричным алгоритмом и при его использовании нужно вводить пароль (парольную фразу), которым ключ зашифрован в хранилище.

Открытая часть используется для:

  • проверки подписи данных;
  • шифрования данных.

❈ ❈ ❈

В закрытой части хранятся закрытые криптоключи, в открытой соответственно открытые криптоключи.

И это действительно важный момент.

Дальше в тексте я буду явно разделять по смыслам слова ключ и криптоключ. Ключ — это такая собирательная сущность OpenPGP/gnupg, объединяющая несколько криптоключей, подписи, identity пользователей и т.п. А криптоключ — это бинарные данные, непосредственно использующиеся в криптоалгоритмах для операций типа подписывания или шифрования.

Криптоключ имеет как минимум открытую часть, а иногда и закрытую. Пара открытый-закрытый криптоключ называется ключевой парой.

Таким образом, если вы хотите кому-то отправить зашифрованный текст, который получатель сможет расшифровать, вы берёте открытый криптоключ этого пользователя, шифруете этим ключом данные. Получатель берёт у себя закрытую компоненту криптоключа и расшифровывает.

Если вы хотите подтвердить/удостоверить подлинность текста, берёте свой закрытый криптоключ, вычисляете при помощи него и первоначального текста специальный набор байтов, называемый электронной подписью, и отправляете подпись вместе с документом. Получатель берёт ваш открытый криптоключ, текст и подпись, скармливает это всё специальному алгоритму, который говорит: «да, эта подпись соответствует этому открытому криптоключу для этого текста». Таким образом получатель может быть уверен, что он получил точно тот же документ, который вы ему отправили.

❈ ❈ ❈

Центральной частью OpenPGP-ключа является мастер-криптоключ, который служит для подтверждения и удостоверения принадлежности данных внутри ключа. Например, все дополнительные крипто-ключи внутри OpenPGP-ключа (их называют подчинёнными ключами/subkeys) подписаны мастер-ключом, чтобы удостоверить их принадлежность. Мастер-криптоключ обычно используется только для подписывания, а для шифрования создаются отдельные подчинённые криптоключи.

Помимо криптоключей в OpenPGP-ключе могут находиться и другие блоки данных: информация об именах пользователей (identity), электронные подписи, даже фотографии.

В рабочей конфигурации gnupg обычно хранится один ваш ключ и несколько ключей других людей или организаций. У сторонних ключей тоже есть мастер-криптоключ, только без закрытой части.

❈ ❈ ❈

Новый OpenPGP-ключ (состоящий из мастер-криптоключа с закрытой частью и криптоключа для шифрования данных тоже с закрытой частью) можно создать такой командой:

$ gpg --gen-key

В процессе вам предложат ввести своё имя, e-mail и пароль для шифрования закрытой части. Весь диалог выглядит примерно так (здесь и далее в листингах полужирным шрифтом показаны вводимые пользователем данные):

gpg (GnuPG) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: keybox '/home/serge/gnupg-demo/pubring.kbx' created
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Sergey Stolyarov
Email address: [email protected]
You selected this USER-ID:
    "Sergey Stolyarov "

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /home/serge/gnupg-demo/trustdb.gpg: trustdb created
gpg: directory '/home/serge/gnupg-demo/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/serge/gnupg-demo/openpgp-revocs.d/57F80A6420E2B1CA6F990F04BB9152FD77C92BB6.rev'
public and secret key created and signed.

pub   rsa3072 2023-07-05 [SC] [expires: 2025-07-04]
      57F80A6420E2B1CA6F990F04BB9152FD77C92BB6
uid                      Sergey Stolyarov 
sub   rsa3072 2023-07-05 [E] [expires: 2025-07-04]

По умолчанию ключ создаётся с датой окончания плюс два года от текущей. Вы можете выбрать другой срок или создать ключ без ограничения срока действия. При необходимости вы можете этот срок продлить, однако выпускать ключ без даты окончания не рекомендуется, так как если вы забудете парольную фразу или потеряете доступ, этот ключ будет бесконечно циркулировать и считаться действующим.

Идентификация ключей

При работе с gpg нужно указывать, какой именно ключ вы хотите использовать, поскольку в рабочей конфигурации их как правило хранится несколько. Как минимум это ваш ключ (закрытая и открытая части), плюс ключи других людей. Первый способ идентификации — через отпечатки (fingerprint) его криптоключей.

По сути отпечаток криптоключа — это набор байтов, который строится на основе байтов открытой части криптоключа (хеш-сумма плюс дополнительные байты). Отпечаток мастер-криптоключа считается отпечатком всего OpenPGP-ключа. Идентификатор (ID) ключа строится из отпечатка следующим образом (для читаемости я разбил на сегменты по 4 символа):

  • отпечаток: 57F8 0A64 20E2 B1CA 6F99 0F04 BB91 52FD 77C9 2BB6
  • короткий идентификатор (short ID): 77C9 2BB6, последние 32 бита отпечатка
  • длинный идентификатор (long ID): BB91 52FD 77C9 2BB6, последние 64 бита отпечатка

❈ ❈ ❈

Помимо отпечатка, вы можете использовать хранимую в ключе информацию о пользователях (identity): имя, часть имени, e-mail, файл с фотографией и так далее. Программа gpg достаточно умная и способна найти ключ, например, лишь по части полного имени.

Поэтому, если у вас в конфиге есть открытый ключ, в пользователях (identity) которого есть емейл [email protected] и вы хотите отправить ему зашифрованный текст, можно команду зашифровки файла test.txt набрать так:

$ gpg -o test.txt.encrypted -r [email protected] -e test.txt

Здесь в параметре -r [email protected] указывается e-mail получателя (-r означает recipient). Вместо e-mail можно указать ID конкретного ключа, или полное имя, или только имя, или фамилию — gpg почти всегда что-то да найдёт, что введённому тексту соответствует.

❈ ❈ ❈

Если вы хотите подписать файл ~/tmp/test.txt (создать цифровую подпись), то это можно сделать так:

$ gpg -u [email protected] -s ~/tmp/test.txt
You need a passphrase to unlock the secret key for
user: "John Smith (esquire) <[email protected]>"
2048-bit RSA key, ID 4600813F, created 2013-03-11

Enter passphrase: 

Здесь имя передаётся в команде -u [email protected]. Цифровая подпись будет создана в файле ~/tmp/test.txt.gpg.

В одних командах для указания ключа используется команда -u (когда используется закрытый ключ), в других — -r (когда используется открытый ключ).

Открытый ключ

Сразу начнём со списка:

$ gpg --list-keys 
/home/serge/gnupg-demo/pubring.kbx
------------------------------------------------------
pub   rsa3072 2023-07-05 [SC] [expires: 2025-07-04]
      57F80A6420E2B1CA6F990F04BB9152FD77C92BB6
uid           [ultimate] Sergey Stolyarov <[email protected]>
sub   rsa3072 2023-07-05 [E] [expires: 2025-07-04]

Если у вас свежий конфиг с одним ключом, то после выполнения команды вы получите у себя в терминале нечто подобное. На примере этого листинга объясню базовые вещи о структуре gnupg-ключа.

Команда --list-keys печатает список всех открытых частей ключей. Каждый ключ отделяется пустой строкой от следующего и состоит из нескольких блоков данных, каждый блок1 в листинге печатается в отдельной строке. В одном ключе скрывается сразу несколько криптоключей, которые используются в разных ситуациях (например, один криптоключ используется для подписывания, другой — для шифрования). Помимо криптоключей, в блоках ключа хранятся и другие данные (о них будет написано ниже).

Начнём с первого блока:

pub   rsa3072 2023-07-05 [SC] [expires: 2025-07-04]
      57F80A6420E2B1CA6F990F04BB9152FD77C92BB6

Первая строка начинается с pub и в ней указываются детали мастер-криптоключа, pub означает, что это открытая часть криптоключа. Остальные поля:

rsa3072
используемый криптоалгоритм и его параметры, в данном случае это RSA с ключом длиной 3072 бит;
2023-07-05
дата создания ключа;
[SC]
здесь указываются Возможности криптоключа (Capabilities, Usage), каждая буква означает свою возможность (их полный список здесь в секции Field 12 - Key capabilities). В нашем случае S означает Sign и C — Certify;
[expires: 2025-07-04]
здесь указывается дата окончания, в нашем примере это 25 июля 2025 года, если ключ без даты окончания, этот фрагмент будет отсутствовать.

Деление на колонки весьма условное, но обычно из контекста понятно, где какие данные. В разных версиях формат вывода может меняться, чтобы получить гарантированный машиночитаемый, добавьте аргумент --with-colons.

Строка 57F80A6420E2B1CA6F990F04BB9152FD77C92BB6 — это отпечаток (fingerprint) криптоключа, я выше писал, как из отпечатка формируется идентификатор.

Теперь следующий блок:

uid           [ultimate] Sergey Stolyarov <[email protected]>

Строка uid означает, что здесь лежит информация о личности/персоне пользователя (по-английски это обозначается identity), по сути весь текст тут является ID этого пользователя. Пользователь служит для привязки бинарных данных ключа к конкретной персоне. В нашем блоке данных user-ID: Sergey Stolyarov <[email protected]>.

Следующий блок:

sub   rsa3072 2023-07-05 [E] [expires: 2025-07-04]

Тип sub означает, что здесь находится открытая часть подчинённого криптоключа. Остальные параметры такие же, как в мастер-криптоключе: RSA-ключ 3072 бита, дата создания — 2023-07-05. Подчинённый криптоключ используется (обратите внимание на флаг возможностей ключа [E], это Encrypt) для шифрования/дешифрования данных (открытая часть для шифрования, закрытая — для дешифрования).

❈ ❈ ❈

По умолчанию при выводе списка ключей идентификаторы криптоключей не отображаются, это можно исправить, если добавить аргумент --keyid-format long:

gpg --keyid-format long --list-keys
/home/serge/gnupg-demo/pubring.kbx
------------------------------------------------------
pub   rsa3072/BB9152FD77C92BB6 2023-07-05 [SC] [expires: 2025-07-04]
      57F80A6420E2B1CA6F990F04BB9152FD77C92BB6
uid                 [ultimate] Sergei Stolyarov (alternative address) <[email protected]>
uid                 [ultimate] Sergey Stolyarov <[email protected]>
sub   rsa3072/4770F007D9F1AAF7 2023-07-05 [E] [expires: 2025-07-04]
sub   rsa2048/E6313E35130E5AF2 2023-07-05 [E] [expires: 2024-07-04]
sub   dsa2048/58A80061F8BDCAEC 2023-07-05 [S] [expires: 2024-07-04]

Идентификаторы добавляются после названия используемого криптоалгоритма.

Закрытый ключ

Список закрытых ключей смотрим командой --list-secret-keys

$ gpg --list-secret-keys                            
/home/serge/gnupg-demo/pubring.kbx
------------------------------------------------------
sec   rsa3072 2023-07-05 [SC] [expires: 2025-07-04]
      57F80A6420E2B1CA6F990F04BB9152FD77C92BB6
uid           [ultimate] Sergey Stolyarov <[email protected]>
ssb   rsa3072 2023-07-05 [E] [expires: 2025-07-04]

Формат вывода здесь такой же, как и для открытых ключей. Обратите внимание, что ID криптоключей здесь те же самые (если указать аргумент --keyid-format long), то есть криптоключи закрытой и открытой частей образуют связную пару.

Здесь sec означает закрытый мастер-криптоключ, он используется для создания подписи данных.

ssb обозначает блок данных с закрытым подчинённым криптоключом. Этот ключ используется для расшифровывания данных, зашифрованных открытым парным криптоключом из предыдущей секции.

При отображении закрытого ключа дублируются все записи о пользователях/identity.

Cуть мастер-криптоключа — он используется для подписывания данных, но не для шифрования. Эти две вещи связаны напрямую, криптоключ для подписывания не просто так был выбран главным в GnuPG-ключе: все важные блоки данных в открытом ключе подписаны мастер-криптоключом. Это означает, что распространяемый открытый ключ невозможно модифицировать, не сломав подписи блоков. Например, если злоумышленник подменит какой-нибудь e-mail (т.е. uid-блок) в открытом ключе, то он не сможет этот подменный блок подписать так, чтобы он прошёл проверку открытой частью мастер-криптоключа.

Распространение открытого ключа

Базовые моменты

Принцип функционирования GnuPG описан много где, поэтому без подробностей: храните зашифрованный уникальной парольной фразой закрытый ключ в надёжном месте, раздавайте свой открытый ключ на все доступные сервера открытых ключей (и не забывайте после обновления ключа опять его загружать на сервер).

Клиент обращается к серверу ключей либо за новым ключом (нужно знать его ID), либо за обновлением уже существующего.

Вот как можно запросить открытый ключ (в данном примере мой настоящий ключ):

$ gpg --keyserver keys.gnupg.net --recv-keys 4695E6355B20C7D2

А вот так можно отправить свой открытый ключ на сервер (это я обновляю свой ключ, поэтому указываю его ID):

$ gpg --keyserver keys.gnupg.net --send-keys 4695E6355B20C7D2

Обновить локальные открытые ключи в конфиге можно командой --refresh-keys, она для каждого ID ключа попытается скачать более новую его версию и обновить записи в конфиге:

$ gpg --refresh-keys --keyserver keys.gnupg.net

Практически все серверы ключей не позволяют удалять блоки данных из ключа. Объяснение этому простое — подписываются только отдельные блоки в ключе, поэтому если удалить блок вместе с его подписью, мы получим валидный (но изменённый злоумышленником) ключ. Поэтому, даже если вы удалите из открытого ключа, например, identity-блок, вы не сможете его удалить с сервера ключей. Неким аналогом удаления блоков является так называемый отзыв, специальный вид цифровой подписи, помечающий блок как более невалидный. Программы обычно такие блоки либо игнорируют как несуществующие, либо выдают специальные предупреждения, если на невалидные блоки завязаны какие-либо действия.

Таким образом, очень внимательно подходите к вопросу выбора имени или добавления подчинённого криптоключа, после публикации открытого ключа «откатить» изменения полностью уже не получится.

Распространение изменений

Два стандартных способа распространения открытого ключа: через экспорт с последующим выкладыванием куда-нибудь или через сервер ключей. Про экспорт на сервер я писал выше (команда --send-keys). А файловый экспорт делается так:

$ gpg --armor -o ~/tmp/57F80A6420E2B1CA6F990F04BB9152FD77C92BB6.pub --export 57F80A6420E2B1CA6F990F04BB9152FD77C92BB6

Если не указывать --armor, то ключ будет выдан в двоичном формате. Дальше этот файл (57F80A6420E2B1CA6F990F04BB9152FD77C92BB6.pub) можно, например, на сайте выложить вместе с такой инструкцией по импорту:

$ gpg --fetch-keys http://example.com/57F80A6420E2B1CA6F990F04BB9152FD77C92BB6.pub

Эта команда сама скачает и затем импортирует ключ в конфиг.

При любом импорте существует несколько сценариев применения изменений, «тонкая настройка» этого делается через команду --import-options, впрочем, действия по умолчанию вполне нормальны и особой необходимости влезать в этот процесс нет.

Редактирование ключа

Базовые моменты

Стандартное редактирование ключа происходит в интерактивном режиме, который запускается командой --edit-key:

$ gpg --edit-key 57F80A6420E2B1CA6F990F04BB9152FD77C92BB6
gpg (GnuPG) 2.2.40; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E   
[ultimate] (1). Sergey Stolyarov <[email protected]>

gpg> 

Также можно вместо ID ключа использовать имя пользователя, вот эквивалентная команда:

$ gpg --edit-key [email protected]

Посмотреть список всех2 доступных команд можно командой help. В процессе выполнения команд данные в ключ сразу не записываются, получается такая типа транзакционность. Записать изменения (и сразу же выйти) можно командой save. Выйти без сохранения можно либо через Ctrl+C, либо командой quit.

Чаще всего при редактировании ключа по-настоящему меняется только открытая часть: редактируется блок данных (либо добавляется новый) и для него создаётся новая подпись.

Также в интерактивный режим редактирования можно войти через другие команды, например, при подписывании чужого ключа своим.

❈ ❈ ❈

Важный момент

Вы можете редактировать любой ключ, а не только свой собственный. Но при запросе данных с сервера ключей удалённые блоки могут приехать снова.

Редактирование пользователя/identity

Наиболее часто используется команда adduid, она добавляет в ключ новый блок с USER-ID/identity: привязать к ключу новый емейл, например; сама команда крайне простая: вводим данные пользователя, вводим парольную фразу ключа и всё:

gpg> adduid
Real name: Sergei Stolyarov
Email address: [email protected]
Comment: alternative address
You selected this USER-ID:
    "Sergei Stolyarov (alternative address) "

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E   
[ultimate] (1)  Sergey Stolyarov 
[ unknown] (2). Sergei Stolyarov (alternative address) 

gpg> 

Ввод парольной фразы нужен для создания подписи для добавленного пользователя, подпись подтверждает, что пользователь добавлен именно владельцем этого ключа.

Чтобы удалить USER-ID, нужно в режиме редактирование сначала выделить его командой uid N, где N — номер user-ID из списка пользователей, на листинге выше номера указаны в круглых скобках перед непосредственно ID. После выделения командой deluid выделенных пользователей можно удалить. Да, выбрать можно сразу несколько пользователей, выбранные в списке отмечаются звёздочкой:

[ultimate] (1)  Sergey Stolyarov <[email protected]>
[ unknown] (2)* Sergei Stolyarov (alternative address) <[email protected]>

Первичный (по-английски — primary) обозначается точкой после номера пользователя, в листинге выше это (1). Сменить первичного пользователя можно так: выделить его (через uid 2, например) и далее команду primary:

gpg> uid 2

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E   
[ultimate] (1)  Sergey Stolyarov 
[ unknown] (2)* Sergei Stolyarov (alternative address) 

gpg> primary

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E   
[ultimate] (1)  Sergey Stolyarov 
[ unknown] (2)* Sergei Stolyarov (alternative address) 

Первичный пользователь используется как пользователь по умолчанию при разруливании всяких сложностей (например, коллизий) или при отображении параметров найденного ключа (например, при вводе парольной фразы), если у вас в ключе несколько пользователей.

Командой deluid можно удалить выделенные блоки с USER-ID, однако смысл в этой команде есть, только если вы ещё не успели поделиться обновлённым открытым ключом с другими или отправть его на сервер ключей.

Командой revuid можно отозвать выделенные user-ID, отозванные пользователи помечаются специальным образом и во многих случаях это почти то же самое, что удалённый. Необходимость в отзыве возникает, например, если вы потеряли один из емейлов и хотите пометить его в списке, чтобы его другие не использовали.

Редактирование подчинённых криптоключей

Блоки криптоключей можно удалять, добавлять и отзывать. Криптоключи бывают двух видов: для подписывания и для шифрования. Создаются они всегда парой: закрытый криптоключ уходит в блок закрытого ключа, а открытый криптоключ — в открытый.

Посмотреть, какие у вас криптоключи, можно командой gpg --list-keys, это те самые [SC], [E] из колонки Возможности. Альтернативно можно посмотреть в команде list режима редактирования:

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E   
[ultimate] (1)  Sergey Stolyarov <[email protected]>
[ unknown] (2)* Sergei Stolyarov (alternative address) <[email protected]>

В списке видно один подчинённый криптоключ, его ID — 4770F007D9F1AAF7. В конце строки можно видеть, как этот криптоключ можно использовать: usage: S означает signing, то есть этим криптоключом можно подписывать сообщения, а usage: E означает encryption, то есть криптоключом можно шифровать данные. Запись usage: SC означает, что ключ можно использовать для подписывания (Signing), удостоверения (Certify, потом расскажу, что это такое). Есть ещё также буква A, которая означает authentication, но на практике это почти не используется (чуть подробнее здесь можно прочитать).

Любой подчинённый криптоключ можно удалить или отозвать.

Создать новый подчинённый криптоключ можно в интерактивном режиме. Например, создадим новый ключ для шифрования данных (RSA 2048 bit, срок жизни 1 год):

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
  (14) Existing key from card
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 2048
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 1y
Key expires at четверг,  4 июля 2024 г. 18:58:36 +07
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E
ssb  rsa2048/E6313E35130E5AF2
     created: 2023-07-05  expires: 2024-07-04  usage: E
[ultimate] (1). Sergei Stolyarov (alternative address) 
[ultimate] (2)  Sergey Stolyarov 

gpg> save

После создания новый криптоключ можно использовать для шифрования или подписывания вместо мастер-криптоключа. Рассмотрим такую конфигурацию:

sec  rsa3072/BB9152FD77C92BB6
     created: 2023-07-05  expires: 2025-07-04  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/4770F007D9F1AAF7
     created: 2023-07-05  expires: 2025-07-04  usage: E
ssb  rsa2048/E6313E35130E5AF2
     created: 2023-07-05  expires: 2024-07-04  usage: E
ssb  dsa2048/58A80061F8BDCAEC
     created: 2023-07-05  expires: 2024-07-04  usage: S
[ultimate] (1). Sergei Stolyarov (alternative address) <[email protected]>
[ultimate] (2)  Sergey Stolyarov <[email protected]>

Здесь у нас:

  • мастер-криптоключ с ID BB9152FD77C92BB6 — этим криптоключом можно создавать электронные подписи (буква S) и удостоверять/сертифицировать (буква C);
  • RSA-криптоключ с ID 4770F007D9F1AAF7 — для шифрования (буква E);
  • RSA-криптоключ с ID E6313E35130E5AF2 — для шифрования;
  • DSA-криптоключ с ID 58A80061F8BDCAEC — для подписывания.

Допустим, какой-то человек получил этот открытый ключ и хочет зашифровать им файл GPL.txt, для этого он использует вот такую команду (результат по умолчанию записывается в GPL.txt.gpg):

$ gpg --recipient [email protected] --encrypt GPL.txt

Каким именно криптоключом будет зашифрован файл? У нас в ключе их два: один с ID 4770F007D9F1AAF7 и второй с ID E6313E35130E5AF2. По умолчанию будет использоваться самый последний из созданных ключей, в нашем случае это подчинённый ключ с ID E6313E35130E5AF2.

Однако можно указать gpg, какой конкретно криптоключ использовать для шифрования (обратите внимание на восклицательный знак после ID подчинённого криптоключа):

$ gpg --recipient 4770F007D9F1AAF7! --encrypt GPL.txt

Восклицательный знак после ID криптоключа заставляет gpg использовать именно этот криптоключ и запрещает обычную процедуру его поиска. Точно такой же метод можно использовать для подписывания данных. Посмотрите на разницу между вот этими двумя командами, отличающимися только лишь одним восклицательным знаком:

$ gpg -o GPL.signed -u BB9152FD77C92BB6 -s GPL.txt
$ gpg --list-packets GPL.signed
...
:signature packet: algo 17, keyid 58A80061F8BDCAEC
    version 4, created 1688558972, md5len 0, sigclass 0x00
    digest algo 8, begin of digest 57 22
    hashed subpkt 33 len 21 (issuer fpr v4 9DB600D2D7C245EBA1CF3A4958A80061F8BDCAEC)
    hashed subpkt 2 len 4 (sig created 2023-07-05)
    subpkt 16 len 8 (issuer key ID 58A80061F8BDCAEC)
    data: [254 bits]
    data: [256 bits]
...

сравните с:

$ gpg -o GPL.signed -u BB9152FD77C92BB6! -s GPL.txt
$ gpg --list-packets GPL.signed
...
:signature packet: algo 1, keyid BB9152FD77C92BB6
    version 4, created 1688559054, md5len 0, sigclass 0x00
    digest algo 8, begin of digest 53 84
    hashed subpkt 33 len 21 (issuer fpr v4 57F80A6420E2B1CA6F990F04BB9152FD77C92BB6)
    hashed subpkt 2 len 4 (sig created 2023-07-05)
    subpkt 16 len 8 (issuer key ID BB9152FD77C92BB6)
    data: [3066 bits]
...

В обоих случаях в качестве пользователя передан ID мастер-криптоключа, однако в первом случае gpg вместо него выбирает ключ автоматически (с ID 58A80061F8BDCAEC). А вот если указать восклицательный знак, то будет использован в точности указанный криптоключ, в данном случае — мастер-криптоключ.

С подписыванием ровно то же самое: непонятно как выбирается ключ для подписи, явно ключ можно указать, добавляя восклицательный знак после ID криптоключа.

Здесь мы использовали команду gpg --list-packets, которая позволяет смотреть структуру OpenPGP-данных.

Подписывание чужого ключа

Одной из главных декларируемых фич OpenPGP является сеть доверия (web of trust), что это такое, можете почитать в википедии (только на английском). В основе сети доверия лежит подписывание ключей, суть его в следующем: если вы доверяете человеку, у вас есть его открытый ключ и вы абсолютно точно уверены, что это именно его открытый ключ, то вы можете подписать его открытый ключ своим закрытым ключом. Такой процедурой вы подтверждаете, что этот ключ действительно принадлежит его владельцу. Чем больше таких авторитетных подписей, тем достовернее и надёжнее ключ (таков ритуал).

Технически всё несколько сложнее, на самом деле вы подписываете/удостоверяете не открытый ключ, а связку пользователь/identity плюс открытый ключ. Везде принято говорить «подписывание ключа», хотя на самом деле вы своей электронной подписью удостоверяете/подтверждаете, что данный UID принадлежит данному открытому ключу.

Для просмотра подписей блоков данных ключа есть команда --list-sigs, она работает как команда --list-keys, только для каждого identity-блока показывает созданные для него подписи:

$ gpg --list-sigs 
/home/serge/gnupg-demo/pubring.kbx
----------------------------------------------------
pub   rsa3072 2023-07-05 [SC] [expires: 2025-07-04]
      57F80A6420E2B1CA6F990F04BB9152FD77C92BB6
uid           [ultimate] Sergei Stolyarov (alternative address) <[email protected]>
sig 3        BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>
uid           [ultimate] Sergey Stolyarov <[email protected]>
sig 3        BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>
sub   rsa3072 2023-07-05 [E] [expires: 2025-07-04]
sig          BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>
sub   rsa2048 2023-07-05 [E] [expires: 2024-07-04]
sig          BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>
sub   dsa2048 2023-07-05 [S] [expires: 2024-07-04]
sig          BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>

Структура листинга аналогична команде --list-keys, только теперь мы видим дополнительные строки — они начинаются со слова sig — это подписи (иногда ещё говорят сигнатуры) для соответствующих блоков. Сразу после создания ключевой пары, у каждого блока в ключе есть только одна подпись, она создана мастер-криптоключом (напомню, что это сделано для того, чтобы можно было безопасно таскать кучку блоков вместе, а целостность (что никто не подменил блок) как раз обеспечивается подписью мастер-криптоключа).

❈ ❈ ❈

Процесс подписывания блоков очень запутанный и нелогичный, поскольку у подписей бывают различные атрибуты (например, уровень доверия), а выставляются они сложным и нелогичным образом. Ниже я рассмотрю несколько типовых и не очень сценариев.

В некоторых сценариях я буду работать с моим собственным открытым ключом с идентификатором 4695E6355B20C7D2, его мы получили в одном из примеров выше. Также я буду пользоваться тестовым ключом (UID: [email protected]), который вы можете установить такой командой:

curl https://raw.githubusercontent.com/sigsergv/blog-data/master/gnupg-explained/jsmith.pub | gpg --import

Простое подписывание ключа

Сценарий: вы получили публичный ключ другого человека ([email protected]), сохранили в конфигурации и хотите подписать (удостоверить) его своим ключом. Типичная команда для этого сценария выглядит так:

% gpg --sign-key [email protected]

pub  rsa3072/8B9E67786ED5FF00
     created: 2023-07-06  expires: 2025-07-05  usage: SC  
     trust: unknown       validity: unknown
sub  rsa3072/F087C814738F7CC3
     created: 2023-07-06  expires: 2025-07-05  usage: E   
[ unknown] (1). John Smith 


pub  rsa3072/8B9E67786ED5FF00
     created: 2023-07-06  expires: 2025-07-05  usage: SC  
     trust: unknown       validity: unknown
 Primary key fingerprint: 7085 056E 4099 C4A6 2CA3  1951 8B9E 6778 6ED5 FF00

     John Smith 

This key is due to expire on 2025-07-05.
Are you sure that you want to sign this key with your
key "Sergei Stolyarov (alternative address) " (BB9152FD77C92BB6)

Really sign? (y/N) y

То есть мы указываем ID/e-mail/имя/часть имени, вводим парольную фразу от нашего закрытого ключа и получаем новую подпись в ключе для [email protected]:

$ gpg --list-sigs [email protected]
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2025-07-04
pub   rsa3072 2023-07-06 [SC] [expires: 2025-07-05]
      7085056E4099C4A62CA319518B9E67786ED5FF00
uid           [  full  ] John Smith 
sig 3        8B9E67786ED5FF00 2023-07-06  John Smith 
sig          BB9152FD77C92BB6 2023-07-06  Sergei Stolyarov (alternative address) 
sub   rsa3072 2023-07-06 [E] [expires: 2025-07-05]
sig          8B9E67786ED5FF00 2023-07-06  John Smith 

Формат вывода при отображении подписей

Структуру строк-подписей рассмотрим на примере этой (это подпись блока для пользователя):

uid           [ultimate] Sergey Stolyarov <[email protected]>
sig 3        BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>

После слова-маркера sig идёт набор из семи флагов подписи, затем ID криптоключа, которым сделана подпись, далее дата создания подписи, а в конце ID пользователя (тут как раз и показывается первичный uid, о котором шла речь чуть выше). Если для данного ID криптоключа в конфиге нет открытого ключа, то вместо строки с информацией о пользователе показывается нечто вроде [User ID not found].

Теперь о флагах, для каждого типа флага отведена одна позиция в списке флагов.

sig 3        BB9152FD77C92BB6 2023-07-05  Sergei Stolyarov (alternative address) <[email protected]>
    ^^^^^^^
    │││││││ 
    ││││││└─ [7] уровень доверия к ключу
    │││││└── [6] `X`, просроченная подпись
    ││││└─── [5] `N`, в подписи есть Notation
    │││└──── [4] `P`, в подписи указан Policy URL
    ││└───── [3] `R`, неотзываемая подпись
    │└────── [2] `L`, неэкспортируемая подпись
    └─────── [1] (0, 1, 2 или 3) уровень проверки

Флаг [1] уровень проверки может содержать 0, 1, 2 или 3, по умолчанию стоит 0. Каждый уровень означает следующее:

0 — нет никакого особого уровня проверки, это значение по умолчанию, вы не думая подписали этот блок.

1 — это означает, что вы считаете, что ключ принадлежит указанной персоне, но никак это не проверяли.

2 — это означает, что вы предприняли самые минимальные усилия, чтобы удостовериться, что ключ принадлежит указанной персоне.

3 — это означает, что вы прям совсем точно знаете, что ключ принадлежит кому надо.

Для своих собственных пользователей ключа, как вы можете видеть из листинга выше, стоит уровень проверки 3, что в принципе логично. Если вы просто создаёте подпись без указания конкретного уровня, то подразумевается уровень 0.

Флаг [2] L показывается, если подпись была создана локальной (неэкспортируемой), локальная подпись не выгружается на ключевые сервера и доступна только для локального использования.

Флаг [3] R показывается, если подпись была помечена как неотзываемая.

Флаг [4] P показывается, если в подписи указан адрес политики подписи, посмотреть список этих адресов можно командой gpg --list-options show-policy-urls --list-sigs.

Флаг [5] N показывается, если в подписи было указано поле Notation, их можно посмотреть комадной gpg --list-options show-notations --list-sigs.

Флаг [6] X показывается, если срок жизни подписи истёк.

Флаг [7] показывает уровень доверия подписи, здесь может быть число от 1 до 9 или буква T, если уровень доверия больше 10.

Простое подписывание ключа с множественными identity

Когда в ключе есть несколько identity, процесс подписи усложняется, поскольку подпись генерируется отдельно для каждой identity-записи и необходимо определиться, доверяем ли мы каждой записи или только некоторым.

Для демонстрации я использую ключ, который можно импортировать такой командой:

curl https://raw.githubusercontent.com/sigsergv/blog-data/master/gnupg-explained/jsmith-multiple.pub | gpg --import

В этом ключе две USER-ID записи, поэтому команда gpg --sign-key [email protected] будет работать по несколько более сложному сценарию:

$ gpg --sign-key [email protected]

pub  rsa3072/8B9E67786ED5FF00
     created: 2023-07-06  expires: 2025-07-05  usage: SC  
     trust: unknown       validity: unknown
sub  rsa3072/F087C814738F7CC3
     created: 2023-07-06  expires: 2025-07-05  usage: E   
[ unknown] (1). John Smith 
[ unknown] (2)  John Smith (work) 

Really sign all user IDs? (y/N) n
Hint: Select the user IDs to sign

gpg> uid 2

pub  rsa3072/8B9E67786ED5FF00
     created: 2023-07-06  expires: 2025-07-05  usage: SC  
     trust: unknown       validity: unknown
sub  rsa3072/F087C814738F7CC3
     created: 2023-07-06  expires: 2025-07-05  usage: E   
[ unknown] (1). John Smith 
[ unknown] (2)* John Smith (work) 

gpg> sign

pub  rsa3072/8B9E67786ED5FF00
     created: 2023-07-06  expires: 2025-07-05  usage: SC  
     trust: unknown       validity: unknown
 Primary key fingerprint: 7085 056E 4099 C4A6 2CA3  1951 8B9E 6778 6ED5 FF00

     John Smith (work) 

This key is due to expire on 2025-07-05.
Are you sure that you want to sign this key with your
key "Sergei Stolyarov (alternative address) " (BB9152FD77C92BB6)

Really sign? (y/N) y

....

gpg> save

Так как мы хотим подписать только один USER-ID, то мы отказываемся от подписывания всех:

Really sign all user IDs? (y/N) n

И дальше выбираем конкретную запись USER-ID и вводим команду для подписи

gpg> uid 2
gpg> sign

Проверяем, что получилось.

% gpg --list-sigs 7085056E4099C4A62CA319518B9E67786ED5FF00
...
pub   rsa3072 2023-07-06 [SC] [expires: 2025-07-05]
      7085056E4099C4A62CA319518B9E67786ED5FF00
uid           [ unknown] John Smith 
sig 3        8B9E67786ED5FF00 2023-07-06  John Smith 
uid           [  full  ] John Smith (work) 
sig 3        8B9E67786ED5FF00 2023-07-06  John Smith 
sig          BB9152FD77C92BB6 2023-07-07  Sergei Stolyarov (alternative address) 
sub   rsa3072 2023-07-06 [E] [expires: 2025-07-05]
sig          8B9E67786ED5FF00 2023-07-06  John Smith 

Подписывание ключей с дополнительными параметрами

Аргумент --sign-key или команда sign в интерактивном режиме подписывает ключ в режиме по умолчанию, создавая обычную подпись. Однако можно создавать и другие типы подписей: локальную, неотзываемую, с декларированным доверием.

Отправка созданных подписей на сервер ключей

Некоторые добавленные локально подписи можно отправить на сервер ключей. Делается это такой командой:

$ gpg --keyserver keys.gnupg.net --send-keys 4695E6355B20C7D2

В результате на сервер keys.gnupg.net уедет созданная вами подпись на пользователя/identity.

Управление ключами

При активном использовании ваш собственный ключ и внешние ключи постоянно меняются:

  • добавляются новые подчинённые ключи;
  • меняются даты окончания ключей;
  • добавляются новые identity;
  • отзываются (revoke) блоки данных;
  • добавляются подписи от других людей.

OpenPGP не навязывает конкретных сценариев управления ключами, однако есть рекомендуемые сообществом подходы и рекомендации. Они вам пригодятся, если вы пользуетесь gnupg в активном сообществе.

  • Выполняйте периодические обновления существующих ключей с серверов ключей.
  • Будьте осторожны с импортом ключей, включая загрузку с серверов ключей. Всегда проверяйте отпечаток (fingerprint) через второй или третий каналы (например, личным звонком или встречей).
  • Для собственных ключей всегда выставляйте дату окончания не более двух лет. При необходимости дату окончания можно продлевать.
  • Создайте и сохраните в безопасном месте сертификат отзыва ключа.
  • Мастер-криптоключ используйте только для сертификации ключей, identity и других блоков OpenPGP-ключей.
  • Для подписывания внешних данных или шифрования используйте только подчинённые ключи.

Защита данных

Шифрование данных

Криптоключ можно использовать для шифрования и дешифрования данных, если он предоставляет такую возможность. Поскольку в ключе хранятся криптоключи асимметричных криптосистем, для шифрования используется открытый криптоключ, а для дешифрования — закрытый. В стандартной конфигурации мастер-криптоключ используется для подписывания, а подчинённый (если он есть) — для шифрования.

Типичная схема здесь: в вашем конфиге есть ключ получателя, вы шифруете файл открытым ключом получателя и отправляете зашифрованные данные, получатель своим закрытым ключом их расшифровывает и получает исходный файл. Однако здесь есть большая проблема — поскольку открытый ключ публичный, злоумышленник может подменить файл, просто зашифровав свои данные этим же общедоступным ключом. Проблема решается через аутентифицированное шифрование (authenticated encryption), когда данные дополнительно подписываются закрытым ключом отправителя.

Вот как выглядит корректное шифрование файла GPL.txt:

$ gpg --encrypt --sign -r [email protected] GPL.txt
gpg: 33C9C3B691AB7DC8: There is no assurance this key belongs to the named user

sub  rsa4096/33C9C3B691AB7DC8 2012-04-18 Sergey Stolyarov 
 Primary key fingerprint: 87E2 946B 041B CF31 8C4D  5BA7 4695 E635 5B20 C7D2
      Subkey fingerprint: 5306 F3FF D40A F9A5 E451  09C3 33C9 C3B6 91AB 7DC8

It is NOT certain that the key belongs to the person named
in the user ID.  If you *really* know what you are doing,
you may answer the next question with yes.

Use this key anyway? (y/N) y

Мы видим стандартное предупреждение, доверяем ли мы этому ключу, соглашаемся, получаем дополнительный вопрос о подписывании, вводим парольную фразу, получаем зашифрованный и подписанный файл GPL.txt.gpg. Обратите внимание, что если не указать аргумент --sign, то передаваемые данные не будут подписаны.

Естественно, получатель должен в своём конфиге иметь ваш OpenPGP-ключ, чтобы аутентифицировать подпись.

Технически аутентифицированное шифрование реализовано в виде схемы: сначала подписываем данные, упаковываем подпись и исходные данные в один блок и дальше шифруем уже его. В результате, если у вас нет закрытого ключа для расшифровки, вы никак не сможете определить, находятся ли внутри OpenPGP-сообщения подписанные или неподписанные данные.

Дешифрование данных

Если вы получили зашифрованный файл GPL.txt.gpg, то расшифровать его (и записать результат в file.txt) можно такой командой:

$ gpg -o file.txt -d GPL.txt.gpg

Если в файле дополнительно присутствует подпись, вы получите сообщение об этом плюс сообщение, удалось ли верифицировать эту подпись.

Что осталось за рамками статьи

Самый главный компонент gnupg-инфраструктуры, о котором я не рассказывал — это GnuPG Agent, это специальная программа для безопасного управления закрытыми ключами. Обычно он работает совершенно прозрачно и вы его присутствие даже не замечаете. Рассказ о нём — это тема отдельной статьи.

Также я не рассказывал детально о принятых в разных сообществах практиках использования OpenPGP (например, в электронной почте или при организации общения сообщества Debian-разработчиков).

Полезное дополнительное чтиво


  1. Вообще, команда --list-keys печатает не все блоки для каждого ключа, например, она не выводит подписи, но для общего понимания структуры ключа это не особо важно. 

  2. На самом деле не всех, часть доступных команд в этом списке отсутствует, видимо, они считаются слишком продвинутыми. Пример такой команды — cross-certify, про неё можно тут почитать. 

Комментарии

Гость: Алексей | 2016-02-10 в 04:19

Спасибо, отличная статья. Может подскажете, как одной командой получить отметку primary uid ключа/ключей? Т.к. количество этих самых uid может быть больше одного и, по моим наблюдениям, primary uid не всегда выводится первым. Явно такой uid отмечается только в режиме редактирования ключа. Особенно интересно в контексте опции --with-colons

Sergey Stolyarov | 2016-02-10 в 09:39

Хороший вопрос! В параметрах --list-keys я не нашёл такого, при использовании --with-colons вроде бы primary uid помечается большими буквами в 12 поле:

  1. Field: Key capabilities: e = encrypt s = sign c = certify a = authentication A key may have any combination of them in any order. In addition to these letters, the primary key has uppercase versions of the letters to denote the usable capabilities of the entire key, and a potential letter 'D' to indicate a disabled key.
Гость: Алексей | 2016-02-10 в 16:33

the primary key has uppercase versions of the letters

Тут речь про ключ, как я понял. А меня интересует uid, у которого я насчитал всего 11 полей. А еще в документации для первого поля упоминается такое:

uid = user id (only field 10 is used).

Эх, жаль.

Текст комментария (допустимая разметка: *курсив*, **полужирная**, [ссылка](http://example.com) или <http://example.com>) Посетители-анонимы, обратите внимение, что более чем одна гиперссылка в тексте (включая оную из поля «веб-сайт») приведёт к блокировке комментария для модерации. Зайдите на сайта с использованием аккаунта на twitter, например, чтобы посылать комментарии без этого ограничения.
Имя (обязательно, 50 символов или меньше)
Опциональный email, на который получать ответы (не будет опубликован)
Веб-сайт
© 2006—2024 Sergey Stolyarov | Работает на pyrengine