В 1991г в США Филом Циммерманом были опубликованы исходные текстов программы PGP (Pretty Good Privacy – замечательная приватность). Эта программа выводила на гражданский рынок самые современные на тот момент алгоритмы шифрования с ассиметричными ключами RSA, ВSA и ElGamal (расширение Diffi-Helman). На тот момент в США действовали довольно жёсткие законы в отношении экспорта криптографических программ и Фил в течении трёх лет подвергался судебному преследованию, но был оправдан, поскольку удалось убедить судей, что исходные тексты программы, это литературное произведение, попадающее под первую поправку к конституции США.
Права на программу PGP несколько раз переходили от одной компании к другой. С начала 2000-х и по настоящее время программой владеет компания Symantec, которая закрыла доступ к исходным кодам программы.
В 1997 году на основе реализации PGP v.5 была разработана группа стандартов OpenPGP. Стандарты описывает требования к алгоритмам шифрования, форматы хранения данных, взаимодействие с почтовыми программами и т.п.
В 1999 в рамках проекта GNU и при финансировании правительства Германии была разработана свободно распространяемая программа шифрования совместимая с OpenPGP – GnuPG версии 1, а в 2006 году - GnuPG версии 2.
В 2014 году вышла версия GnuPG 2.1.0, которая значительно отличается от предшественников (включая версии 2.0.x) по формату файлов. Миграция с 2.0.x на 2.1.x происходит автоматически, обратное преобразование потребует ручного выполнения экспорта-импорта ключей. Кроме того, начиная с версии 2.1.0 прекращена поддержка исторического формата ключей PGP-2. Тем не менее, GnuPG всех версий совместима с классической программой PGP версии 5 и старше.
В 2017 вышла версия GnuPG 2.2.0, которая не сильно отличается о 2.1.x. До этой версии команда gpg
означала GnuPG 1.x, а для новых версий GnuPG использовалась команда gpg2
. Начиная с версии 2.2 во всех новых дистрибутивах команда gpg
означает GnuPG 2.2 и старше.
Реализации GnuPG существуют для всех популярных ОС. Реализация GnuPG для Linux включена во все дистрибутивы, реализация GnuPG для Windows - Gpg4win, для Android OpenKeychain.
Документацию и последние версии GnuPG можно получить на http://www.gnupg.org. На русском языке подробную информацию можно получить на сайте http://www.pgpru.com.
Для интеграции PGP в почтовые программы можно воспользоваться следующими продуктами: Linux, Windows, OS X - плагин для почтового клиента Thunderbird - Enigmail; Android - K9 mail + OpenKeychain; Серверное web-приложение Roundcubemail (ver.>1.2); Gmail и т.п. - расширение для браузеров Mailvelop.
Если не вдаваться в подробности (которые очень важны, если криптография используется по назначению, а не в качестве игрушки), то процесс работы с GnuPG делится на следующие этапы:
На данной странице описаны базовые команды GnuPG 2.x.
Обобщённый формат вызова GnuPG:
gpg --опция ... --команда [имя ключа]
Команды указывают желаемое действие, а опции - параметры для выполнения этого действия. Опции указываются до команд. Некоторые команды переводя gpg в интерактивный режим.
В качестве имени ключа может использоваться цифровой отпечаток (fingerprint), идентификатор ключа (key ID) или e-mail владельца. В дальнейшем имя ключа будет заменяться на mykey .
gpg --gen-key
В GnuPG версии 2.1.x* и старше --gen-key предлагает ввести только имя, e-mail и пароль для секретного ключа, подставляя остальные параметры по умолчанию. Для полного диалога в этих версиях необходимо использовать команду --full-gen-key, возможно с опцией --expert, которая добавляет расширенный выбор алгоритмов шифрования.
В результате выполнения команды --gen-key генерируется два ключа: мастер-ключ, он же ключ подписи, и ключ шифрования. Оба ключа используют алгоритм шифрования rsa2048 и имеют срок жизни два года. Кроме того автоматически формируется сертификат отзыва.
В процессе создания ключа у для него будет создан длинный шестнадцатеричный цифровой отпечаток (fingerprint) который может использоваться для выбора ключа при последующих операциях.
Немного о вводимых параметрах:
Идентификатор владельца ключа (UID) в OpenPGP имеет формат "Полное имя (комментарий) <адрес e-mail>". Идентификатор связывает ключ с определенным человеком. Поскольку OpenPGP в значительной мере ориентирован на использование совместно электронной почтой, то основным идентификатором является e-mail, а полное имя, это лишь вспомогательный элемент.
Пароль для шифрования секретного ключа должен быть достаточно сложным для взлома. Утеря секретного ключа сводит на нет всю систему шифровальной защиты и потому ключ хранится на диске в зашифрованном виде. В идеальном случае ключ должен храниться на съемном носителе (флешке) в физически защищенном месте. Если злоумышленник получит доступ к файлу секретного ключа, то пароль к нему будет последней линией обороны.
Если ключ сертификат отзыва мастер-ключа (revoсation certificate) не был создан во время генерации, то его следует создать, используя команду --gen-revoke. Если секретный ключ будет похищен или утерян, то этот сертификат может быть разослан для уведомления о том, что открытый ключ нельзя больше использовать.
gpg --output revoke.asc --gen-revoke mykey
Сертификат отзыва сохраняется в текстовой кодировке.
К одному ключу можно добавить несколько пользовательских идентификаторов (UID), например, личный и рабочий адреса электронной почты. Операция выполняется в диалоговом режиме.
gpg --edit-key mykey
В диалоговом режиме ввести команду adduid
gpg> adduid
Real Name: My work email
E-mail: my@example.com
После создания нового идентификатора следует отметить степень доверия к нему и назначить, какой UID будет основным. Команда uid
gpg> uid <number>
gpg> trust
(5 = ultimate trust)
gpg> uid <number>
gpg> primary
gpg> save
Удаление идентификатора
gpg> uid <number>
gpg> deluid
Отзыв идентификатора
gpg> uid <number>
gpg> revuid
Перед тем как послать кому-либо открытый ключ необходимо экспортировать его командой --export:
gpg --armor --output alice.gpg --export my@example.com
Опция --armor указывает, что ключ будет сохранён в формате ASCII.
После обмена ключами открытый ключ партнера может быть добавлен к связке открытых ключей при помощи команды --import:
gpg --import blake.asc
gpg --list-keys
/home/alice/.gnupg/pubring.gpg
pub 1024R/B115BDB6 2002–05–01 Alice (test key) <alice@wonderland.uk>
pub 1024R/01A1FE63 2002–05–01 Blake (dumb) <blake@anywhere.ru>
sub 1024R/526C7F7F 2002–05–01 [expires: 2003–05–01]
Для того, чтобы проверить достоверность ключа используется цифровой отпечаток (fingerprint) ключа. После проверки ключ заверяется подписью, для подтверждения того, что он достоверен. Ожидаемый отпечаток ключа передается через надёжный канал связи, например зачитывается владельцем по телефону.
Отпечаток ключа можно просмотреть командой --fingerprint.
gpg --fingerprint alice@wonderland.uk
pub 1024R/B115BDB6 2002–05–01 Alice (test key) <alice@wonderland.uk>
Key fingerprint = DE49 CDEF 12A3 8B7B 272B A572 C73A 9987 B115 BDB6
Или
gpg --fingerprint
/home/test/.gnupg/pubring.gpg
pub 1024R/B115BDB6 2002–05–01 Alice (test key) <alice@wonderland.uk>
Key fingerprint = DE49 CDEF 12A3 8B7B 272B A572 C73A 9987 B115 BDB6
pub 1024R/01A1FE63 2002–05–01 Blake (dumb) <blake@anywhere.ru>
Key fingerprint = 80B8 1955 7D68 FE4F D882 DAD1 D85C 124A 01A1 FE63
sub 1024R/526C7F7F 2002–05–01 [expires: 2003–05–01]
Для подписи ключа необходимо перейти в режим редактирования ключа при помощи команды --edit-key:
gpg --edit-key blake@anywhere.ru
В диалоговом режиме ввести команду sign:
gpg> sign
Подтвердить желание подписать ключ и ввести пароль секретного ключа
Указать, с какой степенью достоверности проверен ключ
gpg> trust
Укажите, насколько Вы доверяете данному пользователю в вопросах проверки
достоверности ключей других пользователей (проверяет паспорт,
сверяет отпечатки ключей из разных источников и т.п.)
1 = Не знаю или не буду отвечать
2 = НЕ доверяю
3 = Доверяю ограниченно
4 = Полностью доверяю
5 = Абсолютно доверяю
Выход из режима редактирования и сохранение изменений
gpg> quit
Для шифрования документа используется команда --encrypt. Для шифрования необходимо иметь открытые ключи предполагаемых получателей. Программа ожидает в качестве параметра имя шифруемого документа или, в случае его отсутствия, шифрует стандартный ввод. Зашифрованный результат помещается в стандартный вывод, если не указана опция --output. Для повышения защиты перед шифрованием документ дополнительно сжимается.
gpg --output message.gpg --encrypt --recipient blake@anywhere.ru message.txt
Опция --recipient может повторяться несколько раз для каждого из предполагаемых получателей и имеет в качестве аргумента идентификатор открытого ключа, которым должен быть зашифрован документ.
При шифровании документа создаётся одноразовый случайный ключ для симметричного шифрования документа, а в зашифрованный документ добавляются несколько копий этого одноразового ключа, каждая из которых зашифрована публичным ключом одного из получателей.
Для расшифровки сообщения используется команда --decrypt. Зашифрованный документ может быть расшифрован только тем, чей секретный ключ соответствует одному из указанных открытых ключей. В частности, отправитель не можете расшифровать зашифрованный им документ, если он не включил свой открытый ключ в список получателей.
gpg --output message.txt --decrypt message.gpg
Для доступа к секретному ключу необходимо ввести пароль
You need a passphrase to unlock the secret key for
user: «Blake (dumb) <blake@anywhere.ru>"
1024-bit RSA key, ID 526C7F7F, created 2002–05–01 (main key ID 01A1FE63)
Enter passphrase:
Документы можно шифровать и без открытого ключа. Вместо этого используется симметричный алгоритм для шифрования документа. Ключ, используемый при шифровании, образуется из ключевой фразы. Для большей безопасности эта ключевая фраза не должна совпадать с той, которая используется для защиты секретного ключа. Симметричный шифр применим, когда есть возможность обменяться ключевой фразой. Для использования симметричного шифра применяется команда --symmetric.
gpg --output message.gpg --symmetric message.txt
Enter passphrase:
Цифровая подпись удостоверяет создателя и дату создания документа. Если документ будет каким-либо образом изменен, то проверка цифровой подписи будет неудачной. При подписи документа используется закрытый ключ подписывающего, а проверяется подпись с использованием его открытого ключа.
Для подписи документов используется команда --sign.
gpg --output file.sig --sign file.bin
You need a passphrase to unlock the secret key for
user: «Alice (test key) <alice@wonderland.uk>"
1024-bit RSA key, ID B115BDB6, created 2002–05–01
Enter passphrase:
Перед подписью документ сжимается. Подписанный документ выводится в двоичном формате.
У подписанный документ можно либо просто проверить подпись, либо проверить подпись и восстановить исходный документ. Для проверки подписи используется команда --verify. Для проверки подписи и извлечения документа используется команда --decrypt.
gpg --output file.bin --decrypt file.sig
gpg: Signature made Sat May 4 19:04:21 2002 MSD using RSA key ID B115BDB6
gpg: Good signature from «Alice (test key) <alice@wonderland.uk>"
Обычно цифровые подписи применяются для отправки электронной почты. При этом нежелательно сжимать подписываемые документы. Команда --clearsign добавляет к документу цифровую подпись в формате ASCII, не изменяя при этом сам документ.
gpg --output doc.asc --clearsign doc.txt
Можно получить подпись, хранящуюся отдельно от документа
gpg --output doc.sig --detach-sign doc.txt
Для проверки подписи необходимы и подпись, и сам документ. Для проверки используется команда --verify.
gpg --verify doc.sig doc.txt
gpg: Signature made Sat May 4 19:34:08 2002 MSD using RSA key ID B115BDB6
gpg: Good signature from «Alice (test key) <alice@wonderland.uk>"
В криптографии существует несколько моделей доверительных отношений:
В модели непосредственного доверия мы самостоятельно проверяем ключи партнёра не полагаясь ни на кого больше. Такая модель доверия используется в SSH, где публичные ключи сервера и клиента представляет из себя набор параметров шифрования и не содержит никакой удостоверяющей информации. Проверка ключа производится самостоятельно путём сличения его цифрового отпечатка с имеющимся в наличии (закэшированном в предыдущем сеансе или размещённого в специальном файле).
В модели иерархического доверия существуют некие изначально доверенные корневые сертификаты, принадлежащие уважаемому центру аутентификации (Central authority, CA). Данный центр подписывает сертификаты доверенных удостоверяющих центров, которые, в свою очередь, подписывают сертификаты серверов и пользователей. Каждый сертификат хранит цепочку подписей, ведущую к корневым сертификатам и позволяет, таким образом, отследить на персональную ответственность за выдачу сертификата. Корневые сертификаты распространяются некоторым надёжным способом, например, как часть дистрибутива ОС или браузера. Эта модель используется в SSL.
Модель сети доверия объединяет обе предыдущие модели. В сети доверия каждый самостоятельно проверяет достоверность чужих сертификатов, но, после проверки, может выступить в качестве удостоверяющего центра для других участников сети. В отличие от централизованной модели здесь никогда не может быть стопроцентной уверенности в подлинности сертификата, но наличие многих участников, независимо подтверждающих достоверность какого-либо сертификата, оказывается вполне достаточным для большинства практических задач.
Для того, чтобы избежать MitM атаки (Man in the middle - расшифровка сообщений в канале передачи) необходимо, удостовериться в том, что публичный ключ партнёра не был подменён. Для достижения этой цели в сертификате ключа OpenPGP хранятся подписи от других участников сети доверия, подтверждающие достоверность хозяина ключа. Хочу обратить внимание, что подписывается не сам ключ, а идентификатор пользователя, привязанный к данному ключу. Так, вы можете быть уверены, что человек действительно использует один из e-mailов, привязанных к ключу, и ничего не знать про другие его e-mailы.
Уровень достоверности того, что сертификат ключа действительно выпущен своим хозяином, высчитывается по количеству подписей и уровня доверия к этим подписям. Получив от нового партнёра по переписке публичный ключ, подписанный людьми, чьи ключи помечены как доверенные, мы повышаем свою уверенность в достоверности полученного ключа.
В оригинальном PGP существовало три степени доверия к подписывающим ключ и три уровня достоверности сертификата.
Уровни доверия:
Уровни достоверности:
В версии GnuPG 2.x появился уровень "Абсолютное доверие" для своих собственных сертификатов.
Чтобы сертификат считался подлинным требуется собственноручная подпись сертификата, или хотя бы одна подпись от полностью доверенного владельца ключа, или две подписи от частично доверенных владельцев ключей.
На самом нижнем уровне этой сети находится личный ключ и личная связка сертификатов. Личный ключ считается абсолютно достоверным а его хозяин (я) абсолютно доверенным. Добавляя чей-либо публичный ключ в связку можно подписать сертификат ключа своим личным ключом, что даст ему статус подлинного сертификата. При этом уровень доверия к владельцу можно установить по своему желанию.
Возможно, что вам не известен уровень доверия к ключам, использованным для подписи ключа партнёра. Тогда вам придётся искать цепочку ключей от известных доверенных ключей к проверяемому. Кроме того, существует некоторая вероятность, что подписавшие ключ люди сговорились (принадлежат к одной тайной организации) и совместно выпустили фальшивый ключ. Поэтому, чем больше людей в мире участвует в подписании ключей, тем проще найти подтверждающую цепочку и тем меньше вероятность сговора. Процедура взаимного подписания ключей при личных контактах, или подписания при абсолютной уверенности в достоверности ключей (например путём сличения цифровых отпечатков по телефону) и создаёт сеть доверия пользователей OpenPGP.
Пример локальной сети доверия можно посмотреть на странице ключей команды разработчиков Arch Linux.
Редактирование уровня доверия к хозяину ключа:
$> gpg --edit-key DA3CE9CE6DF2C45843AB2392D5560606D3C9EE9B
...
gpg> trust
sec rsa2048/D5560606D3C9EE9B
создан: 2020-04-17 годен до: 2022-04-17 назначение: SC
доверие: абсолютное достоверность: абсолютное
ssb rsa2048/C6FF5CA708A972CD
создан: 2020-04-17 годен до: 2022-04-17 назначение: E
[ абсолютно ] (1). Jon Dow <user@example.com>
Укажите, насколько Вы доверяете данному пользователю в вопросах проверки
достоверности ключей других пользователей (проверяет паспорт,
сверяет отпечатки ключей из разных источников и т.п.)
1 = Не знаю или не буду отвечать
2 = НЕ доверяю
3 = Доверяю ограниченно
4 = Полностью доверяю
5 = Абсолютно доверяю
Выдержка из GnuPG FAQ Ru
gpg --edit-key [ID его сертификата] sign
gpg --armor --output signed_cert.asc --export [ID его сертификата]
Следуя этой процедуре, вы сначала убеждаетесь, что говорите с нужным человеком. Сравнивая отпечаток сертификата с тем, который вам сообщили, вы убеждаетесь, что получили нужный сертификат. Еще одна проверка делается, чтобы убедиться, что данный вам адрес перечислен в сертификате. Как только это сделано, вы получаете уверенность, что связали сертификат с реальным человеком. Что и подтверждаете всему миру, подписав сертификат и вернув свежеподписанный сертификат владельцу.
Термин "сертификат" в OpenPGP чаще всего используется в словосочетании "сертификат отзыва", а для структуры данных, связанной с ключом используется просто слово "ключ". На этой странице термин "сертификат" используется, для того, чтобы отличать ключи, как параметры алгоритма шифрования, от ключей, как структур данных.
Структура данных сертификата ключа в OpenPGP позволяет хранить в нём различные дополнительные поля. Подключи - это ключи, которые хранятся в сертификате другого ключа, который называют первичным или мастер-ключом.
Подключи помечаются флагами, которые определяют функциональное назначение подключа. Флаги имеют внутреннее числовое представление, а в информационных утилитах GnuPG помечаются буквами.
0x01 “C” Key Certification
0x02 “S” Sign Data
0x04 “E” Encrypt Communications
0x08 “E” Encrypt Storage
0x20 “A” Authentication
Мастер-ключ автоматически помечается флагами ключа подписи и ключа выпуска сертификатов (CS), поскольку он используется для подписывания подключей и для создания сертификатов отзыва. Отличие ключа шифрования от ключа подписи в том, что ключ подписи действует в будущем. Если его украдут, то злоумышленники смогут в будущем подписывать документы от вашего имени. Поэтому ключ подписи должен иметь ограниченный срок действия и (в случае компрометации) должен быть отозван до окончания срока, чтобы предупредить его использование злоумышленниками. Ключ шифрования действует в прошлом. Его компрометация ведёт к тому, что злоумышленники смогут расшифровать переписку, которая велась с его использованием и никакие отзывы здесь не помогут.
В GnuPG версии 2.1 и старше команда --gen-key создаёт мастер-ключ с функцией подписи и дополнительный подключ с функцией шифрования.
При создании нового подключа задаётся вопрос о его назначении:
$> gpg --edit-key jd@example.com
...
gpg> addkey
Выберите тип ключа:
(3) DSA (только для подписи)
(4) RSA (только для подписи)
(5) Elgamal (только для шифрования)
(6) RSA (только для шифрования)
(14) Existing key from card
Ваш выбор?
Для создания ключа аутентификации необходимо запускать gpg с опцией --expert
Как и во всех системах с асимметричным шифрованием, каждый ключ в OpenPGP представлен парой из публичного и приватного ключа. Публичный используется для шифрования и проверки подписи, а приватный - для подписи и дешифровки.
Для идентификации ключей используется два типа идентификации:
Идентификатор пользователя имеет формат: "Полное имя <адрес e-mail>". Этот идентификатор связывает ключ с определенным человеком. Очевидно, что человек, создающий много ключей, скорее всего, будет использовать для них одинаковые UIDы. К одному ключу можно привязать несколько идентификаторов пользователя, например UIDы для различных почтовых ящиков. Поиск ключа можно вести по полному тексту UID, по e-mail, по полному имени или по его подстроке.
Отпечаток ключа - это хэш SHA-1 длиной 160 бит, вычисляемый на основе открытого ключа и метки времени создания ключа. Для ввода/вывода отпечатка в интерфейсе пользователя используется шестнадцатеричная запись. Длина отпечатка - 40 шестнадцатеричных цифр, которые для удобства разбивают на 10 групп по 4 цифры.
$> gpg --fingerprint -k
...
-----------------------
pub rsa2048 2020-04-17 [SC] [ годен до: 2022-04-17]
DA3C E9CE 6DF2 C458 43AB 2392 D556 0606 D3C9 EE9B
uid [ абсолютно ] John Dow <jd@example.com>
sub rsa2048 2020-04-17 [E] [ годен до: 2022-04-17]
В некоторых ситуациях (при использовании агента) используется ещё один идентификатор ключа - keygrip, который вычисляется как хэш публичного ключа без добавления времени создания.
$> gpg --with-keygrip -k
...
pub rsa2048 2020-04-17 [SC] [ годен до: 2022-04-17]
DA3CE9CE6DF2C45843AB2392D5560606D3C9EE9B
Keygrip = 5D3F2A0BA1DCC59210761397A5CEC5E3393FB111
uid [ абсолютно ] John Dow <jd@example.com>
sub rsa2048 2020-04-17 [E] [ годен до: 2022-04-17]
Keygrip = 0AF602B0376E373F4158E230D0E5E3E9F32F4619
Для экономии времени на ввод идентификатора (или его диктовку по телефону) могут использоваться младшие байты цифрового отпечатка. 16 последних шестнадцатеричных цифр отпечатка называются длинным идентификатором (long ID), а последние 8 символов - коротким идентификатором (short ID). Использование длинного и короткого идентификатора считается плохой практикой, поскольку для них легко сгенерировать коллизии - т.е. различные ключи с совпадающими укороченными ID (но с несовпадающими отпечатками).
В некоторых случаях в начале идентификатора нужно добавлять символы 0x, чтобы подчеркнуть, что это число в шестнадцатеричном виде.
Для того, чтобы не пересчитывать символы руками, команда просмотра публичных ключей --list-keys (-k) позволяет указать опцию --keyid-format, которая может принимать значения 0xLONG, LONG, 0xSHORT, SHORT.
$> gpg --keyid-format 0xSHORT --list-keys
/home/user/.gpg/pubring.kbx
-----------------------
pub rsa2048/0xD3C9EE9B 2020-04-17 [SC] [ годен до: 2022-04-17]
DA3CE9CE6DF2C45843AB2392D5560606D3C9EE9B
uid [ абсолютно ] John Dow <jd@example.com>
sub rsa2048/0x08A972CD 2020-04-17 [E] [ годен до: 2022-04-17]
Личный мастер-ключ должен храниться в очень безопасном месте, желательно на внешнем носителе в физически защищенном месте. Однако использовать такой ключ крайне неудобно: каждый раз, когда вам нужно что-то подписать придётся извлекать ключ из хранилища и использовать его на компьютере с надёжной антивирусной защитой, чтобы избежать перехвата расшифрованного ключа в процессе подписи.
Альтернативой является создание подключей для текущей работы. С помощью мастер-ключа подключам можно назначать небольшой срок жизни, чтобы уменьшить ущерб при их похищении. Так же с помощью мастер-ключа можно отзывать скомпрометированные ключи.
Мастер-ключ извлекается из хранилища и используется в следующих случаях:
Можно использовать различные стратегии устаревания:
Ошибка в GnuPG 2.x: Can’t connect to the agent: Invalid value passed to IPC возникает при выполнении команды:
gpg –-homedir . –-gen-key
Причина: Вся работа с секретными ключами идёт в GnuPG 2.x идёт через gpg-agent, который запускается в фоне при первой необходимости. В данном случае gpg-agent уже запущен и создал сокет в стандартном каталоге * ~/.gpg*
Исправление:
pkill -KILL gpg-agent
gpg-agent --homedir="$(pwd)" --daemon
gpg –-homedir --homedir="$(pwd)" –-gen-key