Шифрование (openssl,gpg)

OpenPGP/GnuPG

В 1991г в США Филом Циммерманом были опубликованы исходные текстов программы PGP (Pretty Good Privacy – замечательная приватность). Эта программа выводила на гражданский рынок самые современные на тот момент алгоритмы шифрования с ассиметричными ключами RSA, ВSA и ElGamal (расширение Diffi-Helman). На тот момент в США действовали довольно жёсткие законы в отношении экспорта криптографических программ и Фил в течении трёх лет подвергался судебному преследованию, но был оправдан, поскольку удалось убедить судей, что исходные тексты программы, это литературное произведение, попадающее под первую поправку к конституции США.

Права на программу PGP несколько раз переходили от одной компании к другой. С начала 2000-х и по настоящее время программой владеет компания Symantec, которая закрыла доступ к исходным кодам программы.

В 1997 году на основе реализации PGP v.5 была разработана группа стандартов OpenPGP. Стандарты описывает требования к алгоритмам шифрования, форматы хранения данных, взаимодействие с почтовыми программами и т.п.

В 1999 в рамках проекта GNU и при финансировании правительства Германии была разработана свободно распространяемая программа шифрования совместимая с OpenPGPGnuPG версии 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

На данной странице описаны базовые команды GnuPG 2.x.

Обобщённый формат вызова GnuPG:

gpg --опция ... --команда [имя ключа]

Команды указывают желаемое действие, а опции - параметры для выполнения этого действия. Опции указываются до команд. Некоторые команды переводя gpg в интерактивный режим.

В качестве имени ключа может использоваться цифровой отпечаток (fingerprint), идентификатор ключа (key ID) или e-mail владельца. В дальнейшем имя ключа будет заменяться на mykey .

Общие опции

  • --homedir /the-secret-place - каталог, в котором хранятся данные gpg. Опция имеет более высокий приоритет, чем переменная окружения GNUPGHOME. По умолчанию в Linux используется каталог ~/.gnupg, в Windows %AppData%\Roaming\gnupg
  • --output file - имя файла для сохранения результата. По умолчанию результат выдаётся на stdout
  • --armor результат выводится в текстовой кодировке (Radix64=Base64+CRC). По умолчанию - результат двоичный

Генерация новой пары ключей

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 помечает/снимает отметку с 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>"

Прозрачно подписанные (сlearsigned) документы

Обычно цифровые подписи применяются для отправки электронной почты. При этом нежелательно сжимать подписываемые документы. Команда --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>"

Доверие к ключам в OpenPGP

В криптографии существует несколько моделей доверительных отношений:

  • Непосредственное доверие
  • Иерархическое доверие
  • Сеть доверия

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

В модели иерархического доверия существуют некие изначально доверенные корневые сертификаты, принадлежащие уважаемому центру аутентификации (Central authority, CA). Данный центр подписывает сертификаты доверенных удостоверяющих центров, которые, в свою очередь, подписывают сертификаты серверов и пользователей. Каждый сертификат хранит цепочку подписей, ведущую к корневым сертификатам и позволяет, таким образом, отследить на персональную ответственность за выдачу сертификата. Корневые сертификаты распространяются некоторым надёжным способом, например, как часть дистрибутива ОС или браузера. Эта модель используется в SSL.

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

Сеть доверия - Web of Trust

Для того, чтобы избежать 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

  1. Встретить владельца сертификата лично.
  2. Попросить показать два документа, удостоверяющих личность.
  3. Убедившись, что человек действительно является тем, за кого он себя выдает, попросите у него отпечаток его сертификата, адрес электронной почты и адрес, по которому можно получить сертификат. (Например: Мой отпечаток 4541 BB01 8EA4 8F99 19CA 3701 2380 6BE5 D6B9 8E10, адрес my@example.com, сертификат можно взять на pool.sks-keyservers.net.)
  4. На своем собственном компьютере получите сертификат этого человека из указанного источника. Убедитесь, что адрес электронной почты, который вам дали, находится в списке адресов, записанных в сертификате. Убедитесь, что отпечаток сертификата, который вы получили, совпадает с отпечатком, который вам дали.
  5. Подпишите сертификат своим ключом gpg --edit-key [ID его сертификата] sign
  6. После подписи экспортируйте подписанный сертификат gpg --armor --output signed_cert.asc --export [ID его сертификата]
  7. Отправьте файл с подписанным сертификатом signed_cert.asc по данному вам адресу.

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

Ключи OpenPGP

Термин "сертификат" в 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 представлен парой из публичного и приватного ключа. Публичный используется для шифрования и проверки подписи, а приватный - для подписи и дешифровки.

Идентификаторы ключа

Для идентификации ключей используется два типа идентификации:

  • человекочитаемый, но не уникальный идентификатор пользователя (user ID, UID)
  • уникальный, но неудобный для ввода цифровой отпечаток ключа (fingerprint, key ID)

Идентификатор пользователя имеет формат: "Полное имя <адрес 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]

Смысл создания подключей

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

Альтернативой является создание подключей для текущей работы. С помощью мастер-ключа подключам можно назначать небольшой срок жизни, чтобы уменьшить ущерб при их похищении. Так же с помощью мастер-ключа можно отзывать скомпрометированные ключи.

Мастер-ключ извлекается из хранилища и используется в следующих случаях:

  • когда вы подписываете чужой ключ или отзываете существующую подпись
  • когда вы создаете новый подключ
  • когда вы добавляете новый UID или помечаете существующий UID как основной
  • когда вы меняете настройки (например, с помощью setpref) для UID
  • когда вы меняете дату истечения срока действия вашего мастер-ключа или любого его подключа
  • когда вы отзываете существующий UID или подключ
  • когда вы отзываете или генерируете сертификат отзыва для ключа со всеми подключами

Время жизни ключа

Можно использовать различные стратегии устаревания:

  1. Мастер-ключ подписи с бесконечным временем жизни. В случае утери или похищения придётся оповещать всех корреспондентов об отзыве старого ключа и каким-то способом оповещать о появлении нового;
  2. Мастер-ключ с бесконечным временем и временные ключи с небольшим сроком жизни, подписанные мастер-ключом. Мастер-ключ хранится отдельно в сейфе. В случае утери временного ключа генерируется и подписывается новый, плюс рассылается сертификат отзыва. Небольшой срок действия ограничит время на взлом пароля для доступа к ключу;
  3. Одноразовые ключи со временем жизни в несколько часов или дней - по обстоятельствам.

Разные мелочи

Ошибка в 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

OpenSSl

История

В 1988 году Международный союз электросвязи (International Telecommunication Union - ITU) опубликовал рекомендации по методам аутенификации в протоколе доступа к службе каталогов (Direcrotry access protocol - DAP). Все рекомендации союза по компьютерным сетям (реализация модели ISO/OSI) маркировались буквой "X" и номером. Серия посвященная службе каталогов получила номера с X.500 и далее. Система аутенификации на основе публичных ключей и сертификатов получила название X.509. В дальнейшем, часть рекомендаций X.500 была реализована в протоколе LDAP, а фреймворк предложенный в X.509 была использована в вебе для реализации протокола SSL и связанной с ним иерархией отношений доверия (RFC 5280).

В частности, X.509 ввёл понятия:

  • сертификат пользователя (сертификат): открытые ключи пользователя вместе с другой вспомогательной информацией, подписанные с помощью секретного ключа, выдавшего его органа по сертификации;
  • центр сертификации (certification authority - CA): орган, которому пользователи доверяют создание и подпись сертификатов. Опционально центр сертификации может создавать и ключи пользователя;
  • путь сертификации: упорядоченная последовательность сертификатов объекта, которая вместе с публичным ключом начального объекта в пути, может быть использована для проверки публичного ключа конечного объекта в пути;
  • доверие: ключевая роль доверия в структуре аутентификации заключается в отношениях между объектом аутентификации и центром сертификации; аутентифицирующий должна быть уверен, что центр сертификации создаёт только действительные и надежные сертификаты.

Для реализации стандарта X.509 и связанных с ним стандартов (алгоритмы шифрования, форматы хранения даннных и т.п.) была разработана библиотека OpenSSL, которая поставляется с утилитой командной строки openssl, и позволяет выполнять все основные криптографические операции. Библиотека Openssl реализована для всех основных ОС, в том числе Linux, Windows, Mac OS, Android и т.д.

Манипуляции с сертификатами

Для корректной работы многих сервисов в современном интернете требуется наличие сертификатов. В качестве примера можно привести HTTPS, SMTP поверх TLS, OpenVPN. В зависимости от сферы применения к сертификатам предъявляются разные требования:

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

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

С OpenVPN поставляется собственный удостоверяющий центр, который позволяет создавать сертификаты сервера и клиента. Сертификат этого центра генерируется локально и добавляется в файл конфигурации клиента и сервера.

LetsEncrypt

Проект LetsEncrypt направлен на массовое внедрение HTTPS в интернете. Он предоставляет бесплатный удостоверяющий центр и наборы скриптов (для разных ОС разные), которые автоматически генерируют пару ключей, создают запрос на выпуск сертификата, отправляют его в удостоверяющий центр LetsEncrypt, а затем автоматически добавляют полученный сертификат в настройки популярных веб-серверов (Apache,Nginx, IIS).

Для почтового сервера достаточно прописать путь к файлу сертификата LetsEncrypt и использовать его совместно с веб-сервером.

EasyRSA

Вместе с OpenVPN поставляется набор скриптов easyrsa (есть под Linux и Windows), которые вызывают openssl для выполнения основных манипуляций с сертификатами. В набор скриптов входят:

  • build-ca - создать приватный ключ удостоверяющего центра (CA)
  • build-key-server - создать серверный приватный ключ и сертификат, подписанный ключом CA
  • build-dh - создать серверный ключ Диффи-Хелмана
  • build-key - создать клиентский приватный ключ и сертификат, подписанный ключом CA
  • build-key-pkcs12 - создать приватный ключ, сертификат и упаковать их вместе сертификатом CA

Версии с добавлением -pass потребуют ввода пароля для шифрования приватного ключа.

В файле openssl.cnf хранятся различные параметры openssl. Многие из них ссылаются переменные окружения, поэтому реальные настройки находятся в файле vars.sh (vars.bat).

vars.sh (фрагмент)

export KEY_SIZE=1024
export CA_EXPIRE=3650
export KEY_EXPIRE=3650

# Атрибуты сертификата
# могут быть изменены в диалоговом режиме
# при создании сертификата
export KEY_COUNTRY="RU"
export KEY_PROVINCE="EKB"
export KEY_CITY="Ekaterinburg"
export KEY_ORG="IMM"
export KEY_EMAIL=""

EasyRSA в подробностях

Внутри скриптов EasyRSA находятся вызовы openssl. Следует помнить, что часть параметров, такие как тип и размер ключа, ключ CA и т.п. находятся в файлt openssl.cnf.

Создание ключа CA без сертификата

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -x509 -keyout ca.key -out ca.csr -config openssl.cnf

Создание пары ключ-сертификат клиента

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -keyout client.key -out client.csr -config openssl.cnf
 #подпись сертификата ключом CA
 openssl ca -days 3650 -out client.crt -in client.csr -config openssl.cnf

то же для сервера

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -keyout srv.key -out srv.csr -config openssl.cnf
 #подпись сертификата ключом CA
 openssl ca -days 3650 -extensions server -in srv.csr -out srv.crt -config openssl.cnf

Экспорт в формат PKCS#12

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -keyout client.key -out client.csr -config openssl.cnf
 #подпись сертификата ключом CA
 openssl ca -days 3650 -in client.csr -out client.crt -config openssl.cnf
 # конвертация пары ключ/сертификат в файл pkcs#12.
 openssl pkcs12 -export -inkeyclient.key -in client.crt -certfile ca.crt -out client.p12

Формат сертификатов

Формальное описание структур данных

Стандарт X.509 предполагает, что все структуры данных, связанные с сертификатами описываются в формате ASN.1. ASN.1 - это архитектурно-независимое представление данных, пригодное для хранения произвольных иерархических структур. На практике, структура ASN.1 кодируется в двоичное представление DER (Distinguished Encoding Rules), описанное в X.690.

Все объектов в ASN.1 имеют уникальные идентификаторы OID (Object Identifier), для которых определены базовые типы данных (числа, строки, коллекции и т.п). OID - это последовательность положительных целых чисел, однозначно идентифицирующая объект. В текстовой записи OID выглядит как десятичные числа, разделяемые точкой - 1.2.345.6.79. Структура OID описывает дерево, корень которого расположен в начале записи. При записи в человекочитаемой форме корневой OID заменяют на некую мнемоническую строку, которую продолжают числовой последовательностью. Например корневой OID ветки, описывающей объекты алгоритма RSA, выглядит так: 1.2.840.113549.1. На специализированном сайте можно выяснить, что это: {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)}. Российский сегмент OID {iso(1) member-body(2) ru(643)} по соглашению с Росстандартом обслуживает ОАО "Инфотекс Интернет Траст". Объекты, связанные с российской криптографией, находятся в ветке 1.2.643.100 и описаны в Приказе ФСБ РФ от 27 декабря 2011 г. N 795 "Об утверждении Требований к форме квалифицированного сертификата ключа проверки электронной подписи".

Для обеспечения уникальности, те или иные OIDы регистрируются некими официальными организациями при координации ISO и ITU. К таким регистрирующим организациям относится IANA, которая выделяет OIDы, необходимые для протоколов сети Интернет (например, LDAP и SNMP). Частная организация может получить стартовый OID, и строить от него поддерево для внутреннего использования. В России регистрацией частных OID занимается ОАО "Инфотекс Интернет Траст".

Просмотр ASN.1 структуры ключа:

openssl asn1parse -in x509-key.pem

Типы сертификатов

  • RFC 5280 описывает формат сертификата X.509 (расширение файла .crt,.cer, .der, .pem) и списка отозванных сертификатов (.clr)

Кроме того, серия документов Public-Key Cryptography Standards (PKCS), созданная корпорацией RSA, описывает различные типы сертификатов X.509. Документы имеют порядковую нумерацию, записанную через #.

  • PKCS #1 (RFC 8017) описывает алгоритм RSA и формат его ключей
  • PKCS #7 (RFC 2315) описывает формат криптографического сообщения (зашифрованного и/или подписанного) (.p7b)
  • PKCS #8 (RFC 5208) описывает формат приватного ключа (.key)
  • PKCS #10 (RFC 2986 ) описывает формат запроса на сертификат (.csr)
  • PKCS #12 (RFC 7292) формат экспорта секретного ключа который вместе с сертификатом и путём сертификации ( .pfx или .p12).

Форматы хранения сертификатов

Основной формат хранения сертификатов X.509 - DER, однако для удобства пересылки по электронной почте его часто дополнительно кодируют в формат PEM (Privacy Enhanced Mail RFC 1421). PEM сам по себе довольно большой стандарт, но из взято только кодирование по алгоритму Base64 и обрамление полученного текста границами:

-----BEGIN label -----
-----END label -----

Для секретных ключей RSA (PKCS#1) используется традиционная форма label, похоже, не описанная в стандартах - RSA PRIVATE KEY.

RFC 7468 описывает форматы label для разных типов ключей и сертификатов

  • CERTIFICATE - сертификат X.509
  • PUBLIC KEY - публичный ключ X.509
  • X509 CRL - список отозванных сертификатов
  • PKCS7 - PKCS#7
  • PRIVATE KEY - PKCS#8
  • ENCRYPTED PRIVATE KEY - RFC 5958
  • CERTIFICATE REQUEST - PKCS#10

За пределами границ BEGIN и END в файл с сертификатом может быть добавлена человекочитаемая версия данных.

Конвертация форматов

Вывод в человекочитаемом формате. noout - отключение вывода в формате PEM:

openssl x509 -in certificate.cer -noout -text

Конвертация PEM -> DER и наоборот:

openssl x509 -inform pem -in certificate.pem -outform der -out certificate.cer
openssl x509 -inform der -in certificate.cer -outform pem -out certificate.pem

Создание файла PFX:

openssl pkcs12 -export -out certificate.pfx -inkey private.key -in certificate.crt -certfile CA.crt

Извлечение приватного ключа RSA из PKCS#8:

openssl pkcs8 -nocrypt -in pkcs8.pem -out pkcs1.pem

CA Bundle

CA Bundle - связка CA - это не особый формат, а просто набор открытых ключей (сертификатов) доверенных центров сертификации в формате PEM, склеенных в один текстовый файл. Формат придуман фирмой Netscape. В Linux CentOS 7 файл /etc/pki/tls/certs/ca-bundle.crt ставится с пакетом ca-certificates-2018.2.22-70. Создать CA Bundle из отдельных файлов можно стандартными средствами ОС:

cat *.pem > ca_bundle.crt

Ссылки

Статья про кроссплатформенное средство просмотра сертификатов

Шифрование/дешифрование

Краткая сводка полезных команд (исключая работу с сертификатами)

Генерация случайных данных/паролей

#сгенерировать 12 байт/16 символов в base64
openssl rand -base64 12

Хэш пароля. Первый вариант - классический DES из passwd, второй - MD5 из shadow. Если salt опустить, то будет сгенерирована случайная строка.

openssl passwd -salt 8E MySecret
openssl passwd -1 -salt sXiKzkus MySecret

Криптографический дайджест файла. В Linux можно использовать эквивалентные команды md5sum, sha1sum.

openssl dgst -md5 filename
openssl dgst -sha1 filename

(Де)Кодирование в BASE64

openssl enc -base64 < file.txt
openssl enc -base64 -in file.txt
openssl enc -base64 -in file.txt -out file.txt.enc

#Декодирование
openssl enc -base64 -d < file.txt.enc

Шифрование симметричными шифрами. Пароль можно вводить интерактивно, читать из файла или указывать в командной строке

#список алгоритмов
openssl list-cipher-commands

#шифрование
openssl enc -des -in file.txt -out file.enc
openssl enc -des -in file.txt -out file.enc -pass pass:mySillyPassword
openssl enc -des -in file.txt -out file.enc -pass file:/path/to/secret/password.txt

#шифрование + кодирование в base64
openssl enc -des -a -in file.txt -out file.asc

#дешифрование
openssl enc -d -des -a -in file.asc -out file.txt

Клиент/сервер

SSL/TLS клиент. На STDERR выводится информация о сертификате. После подключения можно вручную вводить команды соответствующего протокола. TLS доступен только для определённых протоколов.

openssl s_client -connect remote.host:443
openssl s_client -connect remote.host:25 -starttls smtp

Сохранение сертификата в файл penssl s_client -connect remote.host:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p'

Веб сервер с корнем в текущем каталоге. По умолчанию слушает порт 4433.

 openssl s_server -accept 443 -cert mycert.pem -WWW

SSH -OpenPGP

И SSH и OpenPGP используют(могут использовать) алгоритм RSA для аутенификации/шифрования. Соответственно, пары открытый/секретный ключ могут использоваться совместно в двух программах, поскольку это просто числа, соответствующие некой формуле. Основное отличие между ключами в OpenPGP и SSH - это инфраструктура и формат хранения.

Импорт ключа SSH в GPG

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

Для конвертации потребуются скрипты от monkeysphere. Процедура импорта описана ЗДЕСЬ.

Использование GPG для аутенификации в SSH

В gpg-agent встроена поддержка протокола ssh-agent. Соответственно, можно сгенерировать ключи средствами GPG и поместить их в gpg-agent, затем импортировать публичный ключ стандартным образом через ssh-add -L.

Процедура генерации ключа описана ЗДЕСЬ Примерно то же самое + использование ybkey- ССЫЛКА.

GPG4Win и putty

GPG4Win совместим с pagent. ИНСТРУКЦИИ.

Шифрование в OpenSSL ключом OpenSSH

Подготовка

Генерация ключей SSH и сохранение их в пару файлов (mykey,mykey.pub)

ssh-keygen -t rsa -b 4096 -f mykey 

Приватные ключи по умолчанию сохраняются в формате PEM PKCS#1. Ключи, созданные в "новом" формате OpenSSH (опция -o) не совместимы с другими криптографическими системами.

Формат PEM можно отличить по строкам

-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

в файле приватного ключа. В новом формате они заменены на строки

-----BEGIN OPENSSH PRIVATE KEY-----
-----END OPENSSH PRIVATE KEY-----

Публичный ключ так же нужно сконвертировать в формат PEM PKCS#8 (Можно это будет сделать на лету в момент шифрования):

ssh-keygen -f mykey.pub -e -m pkcs8 > mykey.pkcs8.pub
#или
openssl rsa -in mykey -pubout -outform PKCS8 > mykey.pkcs8.pub

Обмениваемся публичными ключами с партнёрами. Чтобы это подчеркнуть, при шифровании я буду использовать чужой публичный ключ anotherkey.pub.

Шифрование

Генерируем одноразовый сеансовый ключ (32 байта):

openssl rand -base64 32 -out key.bin

Шифруем передаваемые данные симметричным ключом:

openssl enc -aes-256-cbc -salt -in bigdata.dat -out bigdata.dat.enc  -pass file:./key.bin

Шифруем сеансовый ключ публичным ключом в формате PKCS#8:

openssl rsautl -encrypt -pubin -inkey anotherkey.pkcs8.pub -in key.bin -out key.bin.enc
# возможна конвертация на лету
openssl rsautl -encrypt -pubin -inkey <(ssh-keygen -e -m PKCS8 -f anotherkey.pub) -in key.bin -out key.bin.enc

Удаляем одноразовый ключ:

rm key.bin

Обмен файлами

По открытому каналу пересылаем bigdata.dat.enc и key.bin.enc.

Расшифровка

Расшифровываем секретным ключом сеансовый ключ. В реальной жизни вместо специально сгенерированного ключа mykey надо будет использовать стандартный ключ ~/.ssh/id_rsa:

openssl rsautl -decrypt -inkey mykey -in key.bin.enc -out key.bin

Расшифровываем данные:

openssl enc -d -aes-256-cbc -in bigdata.dat.enc -out bigdata.dat -pass file:./key.bin

Асимметричное шифрование маленьких файлов

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

# Encrypt openssl rsautl -encrypt -inkey <(ssh-keygen -e -m PKCS8 -f ~/.ssh/id_rsa.pub) -pubin -in small.dat -out small.dat.enc # Decrypt openssl rsautl -decrypt -inkey ~/.ssh/id_rsa -in small.dat.enc -out small.dat