Expertus metuit
Цифровые подписи, криптографические токены, PKCS#11 и linux
Опубликовано 2022-06-23 в 23:48

Эта статья — нечто вроде инструкции по использованию USB криптотокенов в терминале (консоли) линукса и макоси. Ориентирована она прежде всего на российские реалии и рассматривает доступные у нас устройства и программное обеспечение.

Здесь не рассматриваются подробно детали устройства сертификатов и ключей, для этого я рекомендую прочитать статью Ещё больше и лучше о цифровых сертификатах: X.509, PKI, PKCS, где я подробно рассматриваю прикладную криптографию, сертификаты, ключи, а также консольные инструменты для работы с ними.

Базовая операционная система: ubuntu/debian на архитектуре amd64, однако многие сценарии также применимы к макоси версии Catalina или выше (только intel, на arm не проверял), а также для линуксов на другой архитектуре, если для неё существуют подходящие драйверы устройств.

Для работы в макоси вам необходимо сначала поставить homebrew.

❈ ❈ ❈

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

Что такое и зачем нужен криптографический токен

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

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

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

Подготовка рабочего окружения

Мы будем использовать debian/ubuntu последней стабильной версии или macos с установленным homebrew.

Нам понадобятся дополнительные пакеты, которые ставятся в линуксе такой командой:

sudo apt install opensc pcscd

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

brew install opensc

Также понадобится любой эмулятор терминала, в котором мы будем выполнять все действия, в линуксе это может быть xterm, konsole; в макоси — iTerm, но подойдёт любой другой.

Также нам понадобится набор разнообразных токенов, я рассматриваю, например, такие:

  • yubikey
  • rutoken в нескольких вариантах
  • JaCarta

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

OpenSC — это набор свободных программ и библиотек для работы со смарт-картами и с криптографическими токенами в частности. Мы будем работать в основном с утилитой pkcs11-tool.

pcscd — это системный сервис для работы со смарт-картами, он является частью проекта pcsclite.

Существует также альтернативное (и тоже опенсорсное) программное окружение для работы с криптотокена на базе GnuTLS (p11tool, p11-kit), однако в этой статье я его не рассматриваю, поскольку там совершенно иная идеология и архитектура, возможно, я позднее напишу отдельную статью и про неё.

Базовая теория

Мы будем рассматривать токены, поддерживающие PKCS#11 — стандарт, определяющий платформеннонезависимый программный интерфейс Cryptoki к токенам и другим криптографическим устройствам. PKCS#11 входит в большое семейство стандартов PKCS (Public-Key Cryptography Standards), о некоторых из них я рассказывал в своей статье про цифровые сертификаты.

Cryptoki изолирует конкретную реализацию внутри каждого устройства и предоставляет стандартный унифицированный набор функций для выполнения конкретных операций, например, импорт закрытого ключа на устройство или подписывание файла. PKCS#11 реализован практически во всех современных операционных системах. В каких-то он поставляется прямо «из коробки» (windows, macos), а в каких-то требует установки дополнительных пакетов (linux). Для отдельных устройств могут также потребоваться сторонние бинарные модули-библиотеки, реализующие Cryptoki, они обычно предоставляются производителем устройства. По умолчанию в утилите pkcs11-tool используется модуль opensc-pkcs11.so поддерживающий достаточно большое количество устройств. Также у меня будут примеры использования других модулей для конкретных устройств.

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

❈ ❈ ❈

Логическое устройство в терминологии PKCS#11 называется слотом (slot). Логическое устройство, реализующее методы Cryptoki называется токеном (token). В одном физическом устройстве (например, USB-ключе или смарт-карте) может быть несколько токенов, в этом случае они занимают разные слоты.

Элементы данных внутри токена (например, ключи или сертификаты) называются объектами (objects), для доступа к некоторым из них необходима предварительная инициализация сессии (session) посредством процедуры аутентификации, которую я дальше буду называть для краткости «логином». Всего в opensc определены пять типов объектов: cert, privkey, pubkey, secrkey и data. Ниже я подробно расскажу о них.

Каждый поддерживаемый токеном криптографический алгоритм называется механизмом (mechanism). Устройство может возвращать список механизмов, которые оно поддерживает, эта операция рассматривается в разделе Просмотр доступных механизмов токена.

В стандарте определены три типа сессий:

  • обычная пользовательская, через которую выполняются основные операции токена: подписывание файлов, импорт ключа и другие криптографические функции;
  • сессия офицера безопасности/администратора безопасности (security officer, SO), через которую происходит управление пользователями и пинами, в этой сессии криптографические операции запрещены;
  • анонимная сессия, в этом режиме можно получить список незащищённых объектов и базовую информацию об устройстве.

Для каждого типа пользователей существует отдельный пароль, называемый пином (PIN, Personal Identification Number). Без ввода PIN почти никакие операции с токеном невозможны. Также существует ограничение на количество неверных попыток ввода пина, после его превышения пользователь блокируется и данные на устройстве могут быть навсегда заблокированы. Принято пин пользователя обозначать просто как PIN, а пин офицера безопасности как SO PIN.

Формат данных для хранения информации о пользователях покрывается другим стандартом — PKCS#15. Он позволяет задавать различные схемы аутентификации и управления пользователями и пинами. Описанная выше схема с PIN и SO PIN из PKCS#11 является одним из наиболее частых вариантов. Встречаются и другие, например, с PIN и PUK (Personal Unblocking Key), здесь PUK является аналогом SO PIN и он используется для смены PIN, если превышен лимит ошибочных попыток ввода PIN.

Инициализация или персонализация (personalization) токена — это процедура «форматирования» устройства с уничтожением всех имеющихся данных и созданием структуры пользователей, пинов по умолчанию, опциональных ключей, сертификатов и так далее. Как правило после персонализации пользователь токена должен сменить изначальный PIN на собственный. Если вы забыли пин или же превышено количество попыток ввода (включая админский), то форматирование является единственным выходом, если вы собираетесь пользоваться ключом дальше. Все данные при этом уничтожаются.

Чаще всего для персонализации нужно использовать программное обеспечения производителя токена.

❈ ❈ ❈

Токен как и любая смарт-карта работает в соответствии со стандартом ISO 7816, операции PKCS#11 реализуются через команды ISO 7816, однако некоторые смарт-карты также предоставляют доступ к «файловому» интерфейсу ISO 7816, по такому принципу работают «тупые» токены, например, рутокен lite. По сути такие токены можно использовать только в сочетании с подходящим криптопровайдером, например, КриптоПро CSP, Сигнал-КОМ CSP, ViPNet CSP. Криптопровайдер хранит на токене данные (закрытые ключи, сертификаты) в собственном формате, при этом не используются никакие встроенные в токен механизмы защиты данных.

В этом тексте я рассматриваю работу только через PKCS#11, а не через криптопровайдер.

❈ ❈ ❈

Структура PKCS#11-объектов в токене не является чётко формализованной, там нет аналога файловой системы с идентификаторами или именами. Вы можете, например, создать несколько закрытых ключей с одинаковыми метками или идентификаторами, или даже вообще без них. Однако некоторые производители накладывают ограничения на PKCS#11-протокол коммуникации и позволяют выполнять набор или ограниченных операций, или только с конкретно заданными идентификаторами/метками; так делает, например, Yubiko с токенами yubikey.

❈ ❈ ❈

И коротко об основах криптографии.

Symmetric cryptography / Симметричная криптосистема — система шифрования, в которой для шифрования и дешифрования используется один и тот же ключ, его принято называть секретным (secret) ключом. Примеры симметричной криптосистемы — AES, DES, 3DES, ГОСТ 28147-89.

Public-key cryptography / Криптосистема с открытым ключом / Асимметричная криптография — система шифрования, в которой используются два ключа: открытый публичный (public) и закрытый (private), на базе асимметричной криптографии построена система PKI (Public-key infrastructure), цифровых сертификатов (digital certificate) и электронных цифровых подписей (ЭЦП, digital signature). Пример асимметричной криптосистемы — RSA и ECDSA.

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

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

Используемые в статье устройства

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

В каждом из подразделов ниже я пользуюсь командой pkcs11-tool -L для проверки, её вывод детально описан в следующем большом разделе Рецепты → Подключение и распознавание устройства. Также я перечислю установленные по умолчанию пины.

SoftHSM

SoftHSM — это программный эмулятор криптотокена, реализующий интерфейсы спецификации PKCS#11, но не требующий никакого оборудования. Он поддерживает практически все алгоритмы, кроме ГОСТ.

Установка для debian/ubuntu:

sudo apt install softhsm2

Для макоси через homebrew:

brew install softhsm

SoftHSM хранит ключи и настройки в своих каталогах, поэтому сначала их нужно создать:

::shell-session
$ mkdir -p ~/.softhsm-tokens ~/.config/softhsm2

Настраивается SoftHSM через конфигурационный файл, который удобнее и безопаснее всего держать в пользовательском домашнем каталоге: ~/.config/softhsm2/softhsm2.conf. Я сделал базовый конфиг, который вы можете себе скачать и установить такими командами:

::shell-session
$ wget -q -O - 'https://github.com/sigsergv/blog-data/raw/master/security-tokens/softhsm2.conf' \
   | sed "s!\$HOME!$HOME!" > ~/.config/softhsm2/softhsm2.conf 

Дальше проверяем, что всё установилось, у нас должен отобразиться один пустой слот:

::shell-session
$ softhsm2-util --show-slots
Available slots:
Slot 0
    Slot info:
        Description:      SoftHSM slot ID 0x0
        Manufacturer ID:  SoftHSM project
        Hardware version: 2.6
        Firmware version: 2.6
        Token present:    yes
    Token info:
        Manufacturer ID:  SoftHSM project
        Model:            SoftHSM v2
        Hardware version: 2.6
        Firmware version: 2.6
        Serial number:
        Initialized:      no
        User PIN init.:   no
        Label:

Чтобы команда pkcs11-tool увидела это программное устройство, его модуль нужно указать в аргументе --module. Модуль — это подгружаемая библиотека, полный путь к ней можно найти такой командой в макоси:

::shell-session
$ find /usr -name libsofthsm2.so 2>/dev/null
/usr/local/Cellar/softhsm/2.6.1/lib/softhsm/libsofthsm2.so

И в линуксе:

::shell-session
$ find /usr -name libsofthsm2.so 2>/dev/null
/usr/lib/softhsm/libsofthsm2.so
/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so

Однако указывать полный путь нет необходимости, программа умеет сканировать стандартные каталоги (/usr/lib, /usr/local/lib, /usr/lib/x86_64-linux-gnu и т.д.) в поисках файла, так что достаточно указать просто имя библиотеки. Однако это не сработает, если библиотека лежит по нестандартному пути, например, как у SoftHSM.

Теперь мы можем посмотреть список слотов softhsm для макоси:

::shell-session
$ pkcs11-tool --module /usr/local/Cellar/softhsm/2.6.1/lib/softhsm/libsofthsm2.so -T
Available slots:
Slot 0 (0x0): SoftHSM slot ID 0x0
  token state:   uninitialized

И для линукса:

::shell-session
$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -T
Available slots:
Slot 0 (0x0): SoftHSM slot ID 0x0
  token state:   uninitialized

Как мы видим, у нас один слот, причём в нём нет токена, поэтому инициализируем его командой softhsm2-util и сразу смотрим результат (устанавливаем пин в 123456 и «админский» SO PIN в 99999):

::shell-session
$ softhsm2-util --init-token --slot 0 --label 'demo token' --pin 123456 --so-pin 99999
The token has been initialized and is reassigned to slot 2013090016
$ pkcs11-tool --module /usr/local/Cellar/softhsm/2.6.1/lib/softhsm/libsofthsm2.so -T
Available slots:
Slot 0 (0x77fd50e0): SoftHSM slot ID 0x77fd50e0
  token label        : demo token
  token manufacturer : SoftHSM project
  token model        : SoftHSM v2
  token flags        : login required, rng, token initialized, PIN initialized, other flags=0x20
  hardware version   : 2.6
  firmware version   : 2.6
  serial num         : e26bb6e477fd50e0
  pin min/max        : 4/255
Slot 1 (0x1): SoftHSM slot ID 0x1
  token state:   uninitialized

Теперь у нас Slot 0 инициализирован, а также появился пустой Slot 1, это особенность SoftHSM, в нём всегда есть один пустой слот. Также обратите внимание, что в поле token flags появилось значение other flags=0x20, оно соответствует одному флагу — CKF_RESTORE_KEY_NOT_NEEDED, но его значение нас в данный момент не интересует.

Для полного сброса программного токена просто удалите содержимое каталога ~/.softhsm-tokens:

::shell-session
$ rm -rf ~/.softhsm-tokens/*

Важно!

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

Аладдин JaCarta-2 PKI/ГОСТ

Это устройство поддерживает самый большой набор алгоритмов: ГОСТ, RSA, EC, AES и другие. В нём реализовано сразу два токена: один поддерживает отечественные ГОСТ-алгоритмы, второй — зарубежные (RSA).

Токен JaCarta в штатной конфигурации тоже не работает и требует сторонних библиотек, которые можно скачать с официального сайта, нас интересует ПК "Единый Клиент JaCarta 2.13" (версия для 64-битных систем Ubuntu 16/18/20, Debian 9/10), скачиваем архив jacartauc_2.13.11.3194_deb_x64.zip, извлекаем из него пакет jcpkcs11-2_2.7.4.540_x64.deb и устанавливаем. Для работы нужно указать библиотеку libjcPKCS11-2.so.

::shell-session
$ pkcs11-tool --module libjcPKCS11-2.so -L
Available slots:
Slot 0 (0x1ffff): Aladdin R.D. JaCarta [SCR Interface] 00 00
  token label        : JaCarta-2 GOST
  token manufacturer : Aladdin R.D.
  token model        : JaCarta GOST 2.0
  token flags        : login required, rng, token initialized, other flags=0x800
  hardware version   : 1.0
  firmware version   : 2.53
  serial num         : XXXXXXXXXXXXXXX
  pin min/max        : 6/32
Slot 1 (0x2ffff): Aladdin R.D. JaCarta [SCR Interface] 00 00
  token label        : JaCarta#XXXXXXXXXXXXXXX
  token manufacturer : Aladdin R.D.
  token model        : JaCarta Laser
  token flags        : login required, rng, token initialized, user PIN count low, PIN initialized
  hardware version   : 1.1
  firmware version   : 1.0
  serial num         : XXXXXXXXXXXXXXX
  pin min/max        : 4/10

Как мы видим, у этого устройства два слота. В первом слоте (Slot 0) находится токен GOST, который умеет работать с ключами ГОСТ. Во втором слоте (Slot 1) находится токен PKI (Public key infrastructure — инфраструктура на основе открытых ключей), который умеет работать с ключами RSA и EC.

Для работы в макоси нужно скачать и установить пакет ПК "Единый Клиент JaCarta 2.13" (версия для Apple macOS). При запуске указываем нужный модуль:

::shell-session
$ pkcs11-tool --module /Applications/JaCartaUC.app/Contents/MacOS/jcPKCS11-2 -L

Вы можете сократить команду, если сделаете симлинк на этот модуль в системный каталог:

::shell-session
$ sudo ln -s /Applications/JaCartaUC.app/Contents/MacOS/jcPKCS11-2 /usr/local/lib/

После этого можно запускать так:

::shell-session
$ pkcs11-tool --module jcPKCS11-2 -L

Обратите внимание, что ГОСТ-токен в первом слоте JaCarta требует специального ПО для администрирования, которое в открытом доступе отсутствует.

Важно!

Я не рекомендую использовать этот токен, поскольку он слишком сильно завязан на собственное ПО и многие из описанных здесь сценариев к нему неприменимы.

Аладдин eToken PRO 72k

Аладдин eToken PRO 72k поддерживает RSA, AES, 3DES.

OpenSC с модулем по умолчанию не умеет работать с устройством Aladdin eToken PRO 72k (SafeNet eToken 5100):

::shell-session
$ pkcs11-tool -L
Available slots:
Slot 0 (0x0): SafeNet eToken 5100 [Main Interface] 00 00
  (token not recognized)

Модуль jcPKCS11-2 из прошлого сценария поддерживает это устройство.

❈ ❈ ❈

Библиотека для работы с чипом этого токена также входит в состав SafeNet Authentication Client, скачать его можно, например, отсюда. Для линукса нам нужен архив https://www.digicert.com/StaticFiles/SAC_10_7_Linux_GA.zip, для макоси https://www.digicert.com/StaticFiles/SafeNetAuthenticationClient.10.2.82.0.dmg.

Внутри архива для линукса нам нужен пакет safenetauthenticationclient-core_10.7.77_amd64.deb, устанавливаем его, остальные пакеты не нужны. Для макоси ставим пакет SafeNet Authentication Client 10.2.pkg (он предоставляет в том числе графический интерфейс для управления токеном).

После подгрузки модуля всё начинает работать в линуксе:

::shell-session
$ pkcs11-tool --module libeToken.so -L
Available slots:
Slot 0 (0x0): SafeNet eToken 5100 [Main Interface] 00 00
  token label        : eToken
  token manufacturer : SafeNet, Inc.
  token model        : eToken
  token flags        : login required, rng, token initialized, PIN initialized, other flags=0x200
  hardware version   : 4.29
  firmware version   : 0.0
  serial num         : XXXXXXXX
  pin min/max        : 6/20

В макоси команда запуска выглядит так:

::shell-session
$ pkcs11-tool --module libeToken.dylib -L

Если программа падает, попробуйте такой вариант (требует установленного openssl через brew):

::shell-session
$ DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib pkcs11-tool --module libeToken.dylib -L

Рутокен Lite

Рутокен Lite — это самый примитивный по возможностям токен, он умеет только хранить файлы, но не реализует никаких криптографических алгоритмов.

Для линукса нужно скачать библиотеку PKCS#11 с официального сайта, это deb-пакет с именем типа librtpkcs11ecp_2.3.3.0-1_amd64.deb, устанавливаем его и проверяем работу командой pkcs11-tool с указанием нужного модуля:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so -T
Available slots:
Slot 0 (0x0): Aktiv Rutoken lite 00 00
  token label        : Rutoken lite <no label>
  token manufacturer : Aktiv Co.
  token model        : Rutoken lite
  token flags        : login required, rng, token initialized, PIN initialized, user PIN to be changed
  hardware version   : 54.1
  firmware version   : 9.0
  serial num         : XXXXXXXX
  pin min/max        : 6/32

Для макоси нужно скачать библиотеку PKCS#11 с официального сайта, это пакет RutokenInstaller.pkg, устанавливаем его.

Проверяем, что токен распознаётся (нужно указать путь к модулю librtpkcs11ecp.dylib):

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.dylib -L
Available slots:
Slot 0 (0x0): Aktiv Rutoken lite
  token label        : Rutoken lite <no label>
  token manufacturer : Aktiv Co.
  token model        : Rutoken lite
  token flags        : login required, rng, token initialized, PIN initialized, user PIN to be changed
  hardware version   : 54.1
  firmware version   : 9.0
  serial num         : XXXXXXXX
  pin min/max        : 6/32

Важно!

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

Рутокен S

Рутокен S имеет очень ограниченную функциональность при работе через PKCS#11, фактически он идентичен Рутокен Lite. Несмотря на то что на сайте производителя заявлена поддержка алгоритмов ГОСТ, через OpenSC (pkcs11-tool) эти операции не работают.

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

Для debian/ubuntu это пакет ifd-rutokens_1.0.4_amd64.deb; устанавливаем его, перезапускаем демон pcscd (systemctl restart pcscd) и проверяем:

::shell-session
$ pkcs11-tool -L
Available slots:
Slot 0 (0x0): Aktiv Co. Rutoken S 00 00
  token label        : Rutoken S (User PIN)
  token manufacturer : Aktiv Co.
  token model        : PKCS#15
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : XXXXXXXX
  pin min/max        : 8/16

Для макоси скачиваем драйвер из раздела Пользователям Rutoken S и устанавливаем пакет ifd-rutokens.pkg. После перезагружаем систему и проверяем командой pkcs11-tool -L.

Дополнительной библиотеки для работы с PKCS#11 этому токену не нужно.

Важно!

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

Рутокен ECP

Этот токен один из самых функциональных в линейке рутокен и поддерживает на аппаратном уровне множество криптографических алгоритмов, включая ГОСТ и RSA, однако не поддерживает EC (алгоритмы на эллиптических кривых).

Отдельного IFD-драйвера не нужно, однако требуется та же библиотека для PKCS#11, что и для Рутокен lite.

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so -T
Slot 0 (0x0): Aktiv Rutoken ECP 00 00
  token label        : Rutoken ECP <no label>
  token manufacturer : Aktiv Co.
  token model        : Rutoken ECP
  token flags        : login required, rng, SO PIN to be changed, token initialized, PIN initialized, user PIN to be changed
  hardware version   : 54.1
  firmware version   : 23.2
  serial num         : XXXXXXXXXX
  pin min/max        : 6/32

Yubikey 4, Yubikey 4 nano

Yubikey 4, Yubikey 4 nano поддерживают базовые алгоритмы открытых ключей (RSA, ECDSA), не поддерживает алгоритмы симметричного шифрования (например, AES).

Вообще, YubiKey является в первую очередь PIV-устройством (Personal Identity Verification) и разработан по американскому стандарту NIST SP 800-73: Interfaces for Personal Identity Verification. PKCS#11 является одним из доступных интерфейсов, однако его возможности ограничены требованиями PIV. К примеру, нельзя создавать сертификаты/ключи с произвольными идентификаторами, так как предопределённые ID объектов привязаны к PIV-слотам для конкретных целей.

OpenSC частично поддерживает устройства Yubikey 4 без дополнительных библиотек и драйверов как в макоси, так и в линуксе, однако для полной поддержки необходимо установить дополнительный модуль, он входит в состав пакета yubico-piv-tool, скачать который можно с официального сайта: https://developers.yubico.com/yubico-piv-tool/Releases/ в дебиане и убунте он ставится из стандартного репозитория: sudo apt install yubico-piv-tool ykcs11.

После установки запускать нужно с указанием библиотеки libykcs11.so для линукса или libykcs11.dylib для макоси:

::shell-session
$ pkcs11-tool --module libykcs11.dylib -T
Available slots:
Slot 0 (0x0): Yubico YubiKey OTP+FIDO+CCID
  token label        : YubiKey PIV #XXXXXXX
  token manufacturer : Yubico (www.yubico.com)
  token model        : YubiKey YK4
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 1.0
  firmware version   : 4.33
  serial num         : XXXXXXX
  pin min/max        : 6/64

Для некоторых операций, например, полного сброса устройства, вам понадобится YubiKey Manager.

PIN коды по умолчанию

В этом разделе перечислены все пин-коды, установленные в устройствах по умолчанию.

SoftHSM
PIN: 123456, SO PIN: 99999 (именно эти пинкоды используются для инициализации программного токена в этой статье)
Аладдин eToken PRO 72k
PIN: 1234567890, SO PIN: не задан
Рутокен S
PIN: 12345678, SO PIN: 87654321
Рутокен Lite
PIN: 12345678, SO PIN: 87654321
Рутокен ECP
PIN: 12345678, SO PIN: 87654321
Yubikey 4, Yubikey 4 nano
PIN: 123456, PUK: 12345678, SO PIN: 010203040506070801020304050607080102030405060708
Аладдин JaCarta
PKI PIN: 11111111, SO PIN: 00000000, GOST PIN: не задан

Сценарии

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

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

Подключите ваш токен к USB-порту и выполните команду pkcs11-tool -T для получения списка слотов, вот как это выглядит для токена Yubikey:

::shell-session
$ pkcs11-tool -T
Available slots:
Slot 0 (0x0): Yubico YubiKey OTP+FIDO+CCID
  token label        : PIV_II
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 00000000
  pin min/max        : 4/8

Аргумент команды -T означает, что нужно показать только те слоты, в которых есть подходящий токен, для просмотра всех подключенных слотов используется аргумент -L. Вот, например, как выглядит вывод команды pkcs11-tool -L, если к системе подключён считыватель чиповых смарт-карт ACS ACR 38U:

::shell-session
$ pkcs11-tool -L
Available slots:
Slot 0 (0x0): Yubico YubiKey OTP+FIDO+CCID
  token label        : PIV_II
  token manufacturer : piv_II
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 0.0
  firmware version   : 0.0
  serial num         : 00000000
  pin min/max        : 4/8
Slot 1 (0x4): ACS ACR 38U-CCID
  (token not recognized)

Слот без токена в листинге выше выглядит так:

Slot 1 (0x4): ACS ACR 38U-CCID
  (token not recognized)

В поле flags отображаются флаги слота, вот их полный список для версии OpenSC 0.21.0:

  • token present — в слоте имеется токен, если слот и токен совмещены (например, для USB-устройства), то этот флаг всегда выставлен
  • removable device — устройство можно извлечь
  • hardware slot — слот является аппаратным (существуют и программные слоты, например, описанный выше SoftHSM)

В поле token flags отображаются флаги токена, вот их полный список (напомню, что PIN означает пин пользователя, а SO PIN — пин офицера безопасности):

  • login required — в токене имеется как минимум одна криптографическая функция, обязательно требующая логина через ввод PIN
  • PIN pad present — в токене имеется аппаратная панель ввода пина
  • rng — в токене имеется генератор случайных чисел
  • SO PIN count low — лимит неправильных попыток ввода SO PIN почти превышен
  • final SO PIN try — осталась всего одна попытка ввода SO PIN
  • SO PIN locked — офицер безопасности заблокирован
  • SO PIN to be changed — SO PIN необходимо заменить (выставляется, например, после первоначальной инициализации, чтобы офицер безопасности ввёл свой пин вместо изначального, или если срок жизни SO PIN закончился)
  • token initialized — токен инициализирован и пригоден к нормальному использованию
  • user PIN count low — лимит неправильных попыток ввода PIN почти превышен
  • final user PIN try — осталась всего одна попытка ввода PIN
  • PIN initialized — PIN инициализирован
  • user PIN locked — пользователь заблокирован
  • user PIN to be changed — PIN необходимо заменить (выставляется, например, после первоначальной инициализации, чтобы пользователь ввёл свой пин вместо изначального, или если срок жизни PIN закончился)
  • readonly — токен защищён от записи/удаления/добавления каких-то объектов, смены PIN/SO PIN, что конкретно запрещено делать, определяется устройством

Перечисленные token flags определены в OpenSC, однако в PKCS#11 есть дополнительные флаги, которые я тут не указываю. Если они присутствуют в токене, то отображаются в виде other flags=HEX, где HEX — шестнадцатеричное число, состоящее из битов неизвестных библиотеке флагов.

В поле pin min/max отображается минимальная и максимальная допустимая длина пина, в нашем случае это 4/8, то есть пин должен состоять минимум из четырёх и максимум из восьми байтов.

Просмотр доступных механизмов токена

Для получения списка поддерживаемых механизмов (алгоритмов) используется аргумент --list-mechanisms или -M. Для этой операции логин не требуется.

Вот как это выглядит для yubikey 4:

::shell-session
$ pkcs11-tool --list-mechanisms
Using slot 0 with a present token (0x0)
Supported mechanisms:
  SHA-1, digest
  SHA224, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  MD5, digest
  RIPEMD160, digest
  GOSTR3411, digest
  ECDSA, keySize={256,384}, hw, sign, verify, EC OID, EC uncompressed
  ECDSA-SHA1, keySize={256,384}, sign, verify
  ECDSA-SHA224, keySize={256,384}, sign, verify
  ECDSA-SHA256, keySize={256,384}, sign, verify
  ECDSA-SHA384, keySize={256,384}, sign, verify
  ECDSA-SHA512, keySize={256,384}, sign, verify
  ECDH1-COFACTOR-DERIVE, keySize={256,384}, hw, derive, EC OID, EC uncompressed
  ECDH1-DERIVE, keySize={256,384}, hw, derive, EC OID, EC uncompressed
  RSA-X-509, keySize={1024,3072}, hw, decrypt, sign, verify
  RSA-PKCS, keySize={1024,3072}, hw, decrypt, sign, verify
  SHA1-RSA-PKCS, keySize={1024,3072}, sign, verify
  SHA224-RSA-PKCS, keySize={1024,3072}, sign, verify
  SHA256-RSA-PKCS, keySize={1024,3072}, sign, verify
  SHA384-RSA-PKCS, keySize={1024,3072}, sign, verify
  SHA512-RSA-PKCS, keySize={1024,3072}, sign, verify
  MD5-RSA-PKCS, keySize={1024,3072}, sign, verify
  RIPEMD160-RSA-PKCS, keySize={1024,3072}, sign, verify
  RSA-PKCS-PSS, keySize={1024,3072}, hw, sign, verify
  SHA1-RSA-PKCS-PSS, keySize={1024,3072}, sign, verify
  SHA224-RSA-PKCS-PSS, keySize={1024,3072}, sign, verify
  SHA256-RSA-PKCS-PSS, keySize={1024,3072}, sign, verify
  SHA384-RSA-PKCS-PSS, keySize={1024,3072}, sign, verify
  SHA512-RSA-PKCS-PSS, keySize={1024,3072}, sign, verify

А вот как выглядит список механизмов для первого слота (ГОСТ) JaCarta (нумерация слотов начинается с нуля):

::shell-session
$  pkcs11-tool --module /usr/lib/libjcPKCS11-2.so --slot-index 0 -M
Using slot 0 with a present token (0x1ffff)
Supported mechanisms:
  mechtype-0x500, hw, sign
  GOSTR3410-KEY-PAIR-GEN, keySize={512,512}, hw, generate_key_pair
  GOSTR3410, keySize={512,512}, hw, sign, verify
  GOSTR3410-WITH-GOSTR3411, keySize={512,512}, hw, sign, verify
  mechtype-0x1203, hw, wrap, unwrap
  GOSTR3410-DERIVE, hw, derive
  GOSTR3411, hw, digest
  GOSTR3411-HMAC, keySize={256,256}, hw, sign, verify
  GOST28147-KEY-GEN, keySize={256,256}, generate
  GOST28147-ECB, encrypt, decrypt, wrap, unwrap
  GOST28147, encrypt, decrypt, wrap, unwrap
  GOST28147-MAC, keySize={32,32}, sign, verify
  GOST28147-KEY-WRAP, wrap, unwrap
  mechtype-0xC4900001, derive
  mechtype-0xC4900002, hw, verify
  GOSTR3410-12-DERIVE, hw, derive
  GOSTR3410-WITH-GOSTR3411-12-256, keySize={512,512}, hw, sign, verify
  GOSTR3411-12-256, hw, digest
  GOSTR3411-12-512, hw, digest
  GOSTR3411-12-256-HMAC, keySize={256,256}, hw, sign, verify
  GOSTR3411-12-512-HMAC, keySize={512,512}, hw, sign, verify
  mechtype-0xD4321030, hw, derive
  mechtype-0xD4321031, hw, generate
  mechtype-0xD4321032, hw, derive
  mechtype-0xD4321033, hw, derive

Каждая строка определяет один механизм и состоит из его названия и свойств (функций и флагов) через запятую. На самом деле токен сообщает идентификаторы механизмов (например, 0x210) и уже утилита pkcs11-tool преобразует знакомые ей идентификаторы в строки (для 0x210 это MD5). Если идентификатор незнакомый, то он отображается как mechtype-0xD4321033, название и описание механизма можете нагуглить по его значению, например, для 0xD4321033 — это CKM_TLS_GOST_KEY_AND_MAC_DERIVE.

Ниже перечислены возможные свойства (для версии OpenSC 0.22.0).

keySize={ulMinKeySize,ulMinKeySize}
этот атрибут определяет минимальную и максимальную длины поддерживаемых ключей
digest
механизм может использоваться для создания дайджеста
sign
механизм может использоваться для создания электронной цифровой подписи
verify
механизм может использоваться для проверки электронной цифровой подписи
encrypt
механизм может использоваться для шифрования
decrypt
механизм может использоваться для дешифрования
hw
механизм работает на устройстве (hardware)
generate
механизм может использоваться для генерации объекта (например, AES-ключа) на устройстве
generate_key_pair
механизм может использоваться для генерации пары из открытого и закрытого ключей (для асимметричной криптосистемы, например, RSA, ECDSA или ГОСТ Р 34.10-2012)
derive
механизм может порождать ключ из другого ключа
wrap
механизм может маскировать/шифровать (wrap) ключ для экспорта
unwrap
механизм может импортировать маскированный/зашифрованный ключ
EC F_P
механизм можно использовать с параметрами EC над полем Fp
EC F_2M
механизм можно использовать с параметрами EC над полем F2m
EC parameters
механизм может использовать параметры EC непосредственно
EC OID
механизм может использовать параметры EC через указание OID кривой
EC uncompressed
механизм может использовать несжатую (uncompressed) точку эллиптической кривой
EC compressed
механизм может использовать сжатую (compressed) точку эллиптической кривой
EC curve name
механизм может использовать параметры EC через указание кривой (curveName)

Если pkcs11-tool встречает незнакомые флаги, то они указываются в виде other flags=0xXXXXXX. Например, OpenSC версии 0.21 не понимал флагов EC_, поэтому механизм ECDSA, keySize={112,521}, sign, verify, EC F_P, EC OID, EC uncompressed отображался как ECDSA, keySize={112,521}, sign, verify, other flags=0x1900000.

При выполнении криптографических операций можно указывать нужный механизм непосредственно через аргумент --mechanism/-m, ниже будут примеры.

Просмотр списка всех объектов на ключе

Для получения списка объектов используется аргумент --list-objects или его сокращение -O. Если выполнять операцию без логина, то выводится список только публичных объектов.

Вот пример списка публичных объектов (без логина) в программном токене SoftHSM:

::shell-session
$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --list-objects
Using slot 0 with a present token (0x47060dbd)
Data object 2
  label:          'Management Key'
  application:    'Management Key'
  app_id:         1.2.643.999.999
  flags:           modifiable
Certificate Object; type = X.509 cert
  label:
  subject:    DN: C=AQ, O=South Pole Central Bank, CN=SPCB ROOT CA
Public Key Object; RSA 2048 bits
  label:
  ID:         19
  Usage:      encrypt, verify, wrap
  Access:     local

А вот с логином (добавился вывод информации о закрытом ключе):

::shell-session
$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --list-objects --login --login-type user
Using slot 0 with a present token (0x47060dbd)
Logging in to "demo token".
Please enter User PIN:
Private Key Object; RSA
  label:
  ID:         19
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local
Secret Key Object; AES length 16
  label:
  ID:         27
  Usage:      encrypt, decrypt, verify, wrap, unwrap
  Access:     never extractable, local
Data object 4
  label:          'Management Key'
  application:    'Management Key'
  app_id:         1.2.643.999.999
  flags:           modifiable
Certificate Object; type = X.509 cert
  label:
  subject:    DN: C=AQ, O=South Pole Central Bank, CN=SPCB ROOT CA
Public Key Object; RSA 2048 bits
  label:
  ID:         19
  Usage:      encrypt, verify, wrap
  Access:     local

Каждый блок в листинге описывает один объект, у каждого типа объектов свой формат вывода.

Закрытый ключ асимметричной криптосистемы

Тип объекта privkey. Блок для него выглядит так:

Private Key Object; RSA
  label:
  ID:         19
  Usage:      decrypt, sign, unwrap
  Access:     sensitive

Открытый ключ асимметричной криптосистемы (например, RSA)

Тип объекта pubkey. Блок для него выглядит так:

Public Key Object; RSA 2048 bits
  label:
  ID:         19
  Usage:      encrypt, verify, wrap
  Access:     local

Секретный ключ симметричной криптосистемы (например, AES)

Тип объекта secrkey. Блок для него выглядит так:

Secret Key Object; AES length 16
  label:
  ID:         27
  Usage:      encrypt, decrypt, verify, wrap, unwrap
  Access:     never extractable,

Цифровой сертификат

Тип объекта cert. Блок для него выглядит так:

Certificate Object; type = X.509 cert
  label:
  subject:    DN: C=AQ, O=South Pole

Произвольные бинарные данные

Тип объекта data. Блок для него выглядит так:

Data object 4
  label:          'Management Key'
  application:    'Management Key'
  app_id:         1.2.643.999.999
  flags:           modifiable 

При получении списка можно указывать аргумент --type, чтобы показывать только объекты указанного типа, в аргументе можно передать такие значения: cert, privkey, pubkey, secrkey и data.

Запись бинарного файла на устройство

Все рассматриваемые токены позволяют импортировать (записывать) произвольные бинарные файлы на устройство. Есть два режима записи: публичный (public) и закрытый (private). В публичном режиме доступ к записанному объекту можно получить без логина. В закрытом режиме увидеть объект в списке и получить его содержимое можно только после ввода PIN.

Размер доступной памяти у токенов как правило очень не большой и не превышает 100 килобайт.

Для примера создадим два простых текстовых файла user-id.txt и user-key.txt:

::shell-session
$ echo '1234-5678' > user-id.txt
$ echo 'xXx secure key xXx' > user-key.txt 

Записывать данные будем на «тупой» рутокен lite. Стандартно сначала проверяем, видит ли его система:

::shell-session
$ % pkcs11-tool --module librtpkcs11ecp.so -T
Available slots:
Slot 0 (0x0): Aktiv Rutoken lite
  token label        : Rutoken lite <no label>
  token manufacturer : Aktiv Co.
  token model        : Rutoken lite
  token flags        : login required, rng, token initialized, user PIN count low, PIN initialized, user PIN to be changed
  hardware version   : 54.1
  firmware version   : 9.0
  serial num         : XXXXXXXXX
  pin min/max        : 6/32

Сначала запишем в публичном режиме файл user-id.txt:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --type data --application-id '1.2.643.999.888' \
  --application-label AuthManager --label 'User ID' --write-object user-id.txt
Using slot 0 with a present token (0x0)
Created Data Object:
Data object 2197195667
  label:          'User ID'
  application:    'AuthManager'
  app_id:         1.2.643.999.888
  flags:           modifiable

При записи бинарных объектов можно указать несколько дополнительных атрибутов:

  • --application-id '1.2.643.999.888' — идентификатор приложения, обычно здесь записывается OID, в моём случае я использовал выдуманный идентификатор;
  • --application-label AuthManager — название приложения;
  • --label 'User ID' — метка, то есть название объекта.

Для токена объекты представляют собой просто наборы байтов и никак устройством не обрабатываются, этим должно заниматься внешнее использующее токен приложение. Атрибуты как раз и нужны приложению для поиска нужных файлов. Например, идентификатор и название приложения позволяют внешнему ПО находить только «свои» данные. В нашем случае вымышленное приложение AuthManager с идентификатором 1.2.643.999.888 ищёт объект с меткой User ID, чтобы прочитать из него идентификатор пользователя.

Теперь запишем файл user-key.txt в закрытом режиме, на этот раз необходимо указать PIN и аргумент --private, сигнализирующий об особом режиме:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --private --type data \
  --application-id '1.2.643.999.999' --application-label AuthManager --label 'User Key' \
  --write-object user-key.txt
Using slot 0 with a present token (0x0)
Created Data Object:
Data object 1106486004
  label:          'User Key'
  application:    'AuthManager'
  app_id:         1.2.643.999.999
  flags:           modifiable private

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

Чтение бинарного объекта с устройства

Теперь прочитаем записанные в прошлом сценарии объекты. Для начала прочитаем список доступных объектов без логина:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --list-objects --type data
Using slot 0 with a present token (0x0)
Data object 1115237327
  label:          'User ID'
  application:    'AuthManager'
  app_id:         1.2.643.999.888
  flags:           modifiable

Видим, что доступен только один объект, прочитаем его с использованием аргумента --read-object:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --read-object --type data --label 'User ID'
Using slot with index 1 (0x1)
name: John Smith

Мы можем также дополнительно сузить область поиска и указать дополнительно аргументы --application-id или --application-label, в этом случае, будет прочитан только тот объект, у которого атрибуты совпадут со значениями переданных аргументов.

❈ ❈ ❈

Теперь запросим список всех объектов, на этот раз с логином и пином:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --list-objects --type data
Using slot 0 with a present token (0x0)
Data object 1100700891
  label:          'User Key'
  application:    'AuthManager'
  app_id:         1.2.643.999.999
  flags:           modifiable private
Data object 1117461659
  label:          'User ID'
  application:    'AuthManager'
  app_id:         1.2.643.999.888
  flags:           modifiable

Если мы теперь попытаемся так же без логина прочитать закрытый объект, то получим ошибку:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --read-object --type data --label 'User Key'
Using slot with index 1 (0x1)
error: object not found
Aborting.

Однако после логина (аргументы --login --pin 12345678) данные читаются:

::shell-session
$ pkcs11-tool --login --pin 12345678 --module librtpkcs11ecp.so --read-object --type data --label 'User Key'
Using slot 0 with a present token (0x0)
xXx secure key xXx

Содержимое объекта по умолчанию выводится в терминал, однако можно его сохранить в файл FILE_NAME через аргумент --output-file FILE_NAME.

Также обратите внимание, что аргумент --type обязательный, в нём нужно указывать тип данных объекта, который нам нужен.

Удаление объекта с устройства

Продолжим с тем же токеном, удалим записанные ранее данные. Публичный объект можно удалить из устройства такой командой:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --delete-object --type data --label 'User ID' 

Закрытый объект можно удалить только после указания PIN:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --slot-index 1 --login --pin 12345678 \
  --delete-object --type data --label 'User Key' 

Атрибут --type нужно указывать обязательно, без него команда не сработает. Набор аргументов для выбора объекта для удаления отличается для разных типов.

В случае бинарных объектов (--type data) можно указать: --label, --application-label, --application-id, --object-index. Последний аргумент — --object-index — позволяет указать номер объекта из списка --list-objects (для данного типа объектов), который нужно удалить, нумерация идёт с нуля. Например, если команда с аргументами --list-objects --type data выдаёт объекты A, B, C, то команда с аргументом --object-index 1 удалит объект B. Однако если выполнить команду с логином и --list-objects --type data выдаст объекты X, Y, A, B, C, D, то для удаления объекта B при заданном PIN нужно указывать другой индекс — --object-index 3.

В случае закрытых ключей (--type privkey) асимметричных криптосистем (ГОСТ, RSA или EC) можно указать: --label, --id, --object-index.

В случае открытых ключей (--type pubkey) асимметричных криптосистем (ГОСТ, RSA или EC) можно указать: --label, --id, --object-index.

В случае секретных ключей (--type secrkey) симметричных криптосистем (AES, 3DES) можно указать: --label, --id, --object-index.

В случае сертификатов (--type cert) можно указать: --label, --object-index

Запись закрытого ключа асимметричной криптосистемы (RSA и EC)

Для тестов сгенерируем закрытый ключ RSA 2048 бит через openssl:

::shell-session
$ openssl genrsa -out aqts-root-ca.pem 2048

Теперь его можно импортировать в токен такой командой (пример для Рутокен ECP в первом слоте):

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --slot-index 0 --login --pin 12345678 --type privkey \
  --write-object aqts-root-ca.key --id 13
Using slot with index 0 (0x0)
Created private key:
Private Key Object; RSA
  label:
  ID:         13
  Usage:      decrypt, sign
  Access:     sensitive

Эта операция всегда требует логина. Закрытый ключ можно записать только на устройство, которое их поддерживает именно как закрытые ключи. Если вы попытаетесь это сделать с токеном, который не понимает этот алгоритм, то получите ошибку. Например, так это выглядит при попытке записать закрытый RSA-ключ на Рутокен S:

::shell-session
$ pkcs11-tool --login --pin 12345678 --type privkey --write-object aqts-root-ca.key --id 13
Using slot 0 with a present token (0x0)
error: PKCS11 function C_CreateObject failed: rv = CKR_GENERAL_ERROR (0x5)
Aborting.

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

❈ ❈ ❈

Теперь рассмотрим ключи ECDSA. Сначала сгенерируем ECDSA-ключ в файле spcb-root-ca-key.pem такими командами:

::shell-session
$ openssl ecparam -name prime256v1 -genkey -out spcb-root-ca-key.pem
$ openssl ec -in spcb-root-ca-key.pem -outform DER -out spcb-root-ca.key

Запишем ключ из файла spcb-root-ca-key.pem во второй слот JaCarta:

::shell-session
$ pkcs11-tool --module jcPKCS11-2 --slot-index 1 --login --pin 11111111 --type privkey --write-object spcb-root-ca-key.pem --id 14
Using slot with index 1 (0x2ffff)
Created private key:
Private Key Object; EC
  label:
  ID:         14
  Usage:      sign
  Access:     sensitive, always sensitive, never extractable

Обратите внимание, что в поле Usage у ключа стоит только значение sign, в отличие от RSA, алгоритм ECDSA может использоваться только для создания и проверки цифровой подписи. В то время как RSA-ключ можно использовать для шифрования и дешифрования.

❈ ❈ ❈

Мне не удалось записать через pkcs11-tool на рутокен ECP ключи криптосистемы ГОСТ (ни ГОСТ Р 34.10-2001, ни ГОСТ Р 34.10-2012), возможно, это получится, если как-то пересобрать openssl или OpenSC, но заниматься этим я не хочу.

Запись открытого ключа асимметричной криптосистемы RSA и EC

В прошлом сценарии мы сгенерировали закрытый ключ RSA aqts-root-ca.pem, вытащим из него открытый ключ в файл aqts-root-ca-pubkey.pem:

::shell-session
$ openssl rsa -in aqts-root-ca.pem -pubout -out aqts-root-ca-pubkey.pem

И запишем его в Рутокен ECP:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --slot-index 0 --login --pin 12345678 --type pubkey \
  --write-object aqts-root-ca-pubkey.pem --id 12
Using slot with index 0 (0x0)
Created public key:
Public Key Object; RSA 2048 bits
  label:
  ID:         12
  Usage:      encrypt, verify
  Access:     none

В поле Usage указаны атрибуты, описывающие доступные функции для этого объекта, в нашем случае это шифрование (encrypt) и верификация цифровой подписи (verify). В качестве идентификатора мы указываем то же значение, что мы указали для иходного закрытого ключа.

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

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --slot-index 0 --type pubkey --read-object --id 12
...

Содержимое выдаётся в бинарном виде в DER-кодировке.

❈ ❈ ❈

Аналогично выделим открытый ключ из закрытого ключа spcb-root-ca-key.pem в файл spcb-root-ca-pubkey.pem:

::shell-session
$ openssl ec -in spcb-root-ca-key.pem -pubout -out spcb-root-ca-pubkey.pem 

И запишем его на токен JaCarta PKI:

::shell-session
$ pkcs11-tool --module jcPKCS11-2 --slot-index 1 --login --pin 11111111 --type pubkey \
  --write-object spcb-root-ca-pubkey.pem --id 14
Using slot with index 1 (0x2ffff)
Created public key:
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   044104676b4d1591780c87205c4aad8bececd4ff951a12644c3714b267f8e4bac9391a76720de7ef1ea25373aa1eb23c43c72df591ba0a55b81a1ebab539f0a09b1a37
  EC_PARAMS:  06082a8648ce3d030107
  label:
  ID:         14
  Usage:      verify
  Access:     none

Запись секретного ключа симметричной криптосистемы (AES)

Сначала сгенерируем на компьютере секретный ключ AES длиной 128 бит и запишем его в файл aes128.key, это просто набор случайных байтов, поэтому воспользуемся генератором псевдослучайных чисел из openssl:

::shell-session
$ openssl rand 16 > aes128.key

Далее импортируем его на программный токен SoftHSM такой командой (для макоси путь к модулю другой — /usr/local/Cellar/softhsm/2.6.1/lib/softhsm/libsofthsm2.so):

::shell-session
$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --login --pin 123456 --type secrkey \
  --write-object aes128.key --id 232 --key-type AES:16
Using slot 0 with a present token (0x47060dbd)
Created secret key:
Secret Key Object; AES length 16

  label:
  ID:         0232
  Usage:      encrypt, decrypt, verify, wrap, unwrap
  Access:     none

Для успешного выполнения команды устройство должно поддерживать нужный механизм, в противном случае вы получите ошибку. Среди рассматриваемых устройств AES поддерживают только eToken PRO 72k, JaCarta и SoftHSM.

Если вы попытаетесь записать, например, на рутокен lite, то получите такую ошибку:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --type secrkey --write-object aes128.key \
  --id 232 --key-type AES:16
Using slot 0 with a present token (0x0)
error: PKCS11 function C_CreateObject failed: rv = CKR_TEMPLATE_INCONSISTENT (0xd1)
Aborting.

Секретный ключ нельзя экспортировать с токена (то есть прочитать с аргументом --read-object). Некоторые устройства (например, eToken PRO 72k) не поддерживают запись секретного ключа, его можно только сгенерировать на самом устройстве.

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

Мы сгенерируем пару RSA-ключей с идентификатором 5, для этой операции необходим логин. Для программного токена SoftHSM команда выглядит так:

::shell-session
$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --login --login-type user --pin 123456 \
  --keypairgen --key-type RSA:2048 --id 5
Using slot 0 with a present token (0x74c7dcd5)
Key pair generated:
Private Key Object; RSA
  label:
  ID:         05
  Usage:      decrypt, sign, unwrap
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; RSA 2048 bits
  label:
  ID:         05
  Usage:      encrypt, verify, wrap
  Access:     local

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

Также обратите внимание, что если команду генерации запустить несколько раз, будет создано несколько объектов с одним и тем же идентификатором.

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

Сгенерируем пару ключей для алгоритма ECDSA на подходящем устройстве (JaCarta PKI, Yubikey4, SoftHSM). Вариант с Yubikey я рассмотрю отдельным сценарием, так как там свои особенности, а здесь — общий случай на примере JaCarta PKI. Для гарантии мы так же принудительно укажем механизм, который нужно использовать для генерации:

::shell-session
$ pkcs11-tool --module jcPKCS11-2 --slot-index 1 --login --pin 11111111 --keypairgen --key-type EC:secp521r1 \
  --id 29 --label 'EC Signature Key' --mechanism ECDSA-KEY-PAIR-GEN
Using slot with index 1 (0x2ffff)
Key pair generated:
Private Key Object; EC
  label:      EC Signature Key
  ID:         29
  Usage:      sign, derive
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 528 bits
  EC_POINT:   0481850400772c754d33dabd552d6bb..........0f262d31796ccfc9683fcd89
  EC_PARAMS:  06052b81040023
  label:      EC Signature Key
  ID:         29
  Usage:      verify, derive
  Access:     local

Также обратите внимание, что если команду генерации запустить несколько раз, будет создано несколько объектов одного типа с одним и тем же идентификатором.

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

Для Yubikey нельзя указывать произвольные идентификаторы, для ключей разных типов зарезервированы значения, которые вы должны использовать. Кроме того, для генерации и записи ключей нужно логиниться с правами оператора безопасности и соответствующим SO PIN, который в терминологии Yubikey называется PIV management key.

::shell-session
$ pkcs11-tool --module libykcs11.dylib --login --login-type so --keypairgen --key-type EC:prime256v1 \
  --id 2 --label 'demo ec key'
Using slot 0 with a present token (0x0)
Logging in to "YubiKey PIV #XXXXXXXX".
Please enter SO PIN:
Key pair generated:
Private Key Object; EC
  label:      Private key for Digital Signature
  ID:         02
  Usage:      decrypt, sign
  Access:     always authenticate, sensitive, always sensitive, never extractable, local
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   04410492c5df3f8ee224...............7e3cdde
  EC_PARAMS:  06082a8648ce3d030107
  label:      Public key for Digital Signature
  ID:         02
  Usage:      encrypt, verify
  Access:     local

Обратите внимание, что мы указываем --label 'demo ec key', однако в созданных объектах метка другая. Это происходит оттого, что интерфейс PKCS#11 является вторичным по отношению к PIV, в котором ключи и сертификаты на устройстве присутствуют не просто так, а с определёнными ролями. В данном случае для ключа/сертификата с идентификатором 2 роль — цифровая подпись, и поэтому библиотека подменяет метку на заранее предопределённое значение.

Генерация ключевой пары ГОСТ Р 34.10-2001 на устройстве

Криптосистема ГОСТ Р 34.10-2001 является устаревшей и многими современными системами уже не поддерживается или прямо запрещается. Вместо неё нужно использовать ГОСТ Р 34.10-2012.

Чтобы сгенерировать ключевую пару по алгоритму ГОСТ Р 34.10-2001, вам необходим подходящий токен, например, рутокен ECP или первый слот на JaCarta ГОСТ/PKI. Вот как это делается на рутокен ECP с параметром ключей A (OID 1.2.643.2.2.35.1):

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --keypairgen --key-type GOSTR3410-2001:A --id 5
Using slot 0 with a present token (0x0)
Key pair generated:
Private Key Object; GOSTR3410
  PARAMS OID: 06072a850302022301
  label:
  ID:         05
  Usage:      sign
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; GOSTR3410
  PARAMS OID: 06072a850302022301
  VALUE:      df8852a979e9e5c04713bb6980ca89e32a7e2d9398a5ad1119758a70b2a6668c
              cdef6d5f123af2c09969c155d835da16d3f839889d704e93ce957185fdcad154
  label:
  ID:         05
  Usage:      verify
  Access:     local

Для этого алгоритма в OpenSC доступны следующие наборы параметров:

  • GOSTR3410-2001:A, id-GostR3410-2001-CryptoPro-A-ParamSet, OID 1.2.643.2.2.35.1, «ГОСТ Р 34.10-2001, параметры по умолчанию»
  • GOSTR3410-2001:B, id-GostR3410-2001-CryptoPro-B-ParamSet, OID 1.2.643.2.2.35.2, «ГОСТ Р 34.10-2001, параметры Оскар 2.x»
  • GOSTR3410-2001:C, id-GostR3410-2001-CryptoPro-C-ParamSet, OID 1.2.643.2.2.35.3, «ГОСТ Р 34.10-2001, параметры подписи 1»

OpenSC не умеет читать (экспортировать) открытые ключи этого алгоритма:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --read-object --id 5 --type pubkey
Using slot 0 with a present token (0x0)
error: Reading public keys of type 0x30 not (yet) supported
Aborting.

Генерация ключевой пары ГОСТ Р 34.10-2012 на устройстве

Генерация ключевой пары алгоритма ГОСТ Р 34.10-2012 с длиной ключа 512 бит и набором параметров A (ключи длиной 256 бит на рутокен ECP не поддерживаются):

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --keypairgen --key-type GOSTR3410-2012-512:A --id 9
Using slot 0 with a present token (0x0)
Key pair generated:
Private Key Object; GOSTR3410-2012-512
  PARAMS OID: 06092a8503070102010201
  label:
  ID:         09
  Usage:      sign
  Access:     sensitive, always sensitive, never extractable, local
Public Key Object; GOSTR3410-2012-512
  PARAMS OID: 06092a8503070102010201
  VALUE:      ce3dca41376967350e922edbdee89c148300b80cc3163110ed645bca9ccaa58c
              c5757bc5cbad891a4da6a5e25f1b84c957a3443ed2740a1a94e09495ea61117c
              a8488c16fa34ed5519bf28fff79d7dc5a601e1e3744e58930a39328226463832
              0a9744aa1e6fbdf1190ec6a50efa061d138755c8b8e80dd5bacbe5eb1fab3641
  label:
  ID:         09
  Usage:      verify
  Access:     local

Для этого алгоритма в OpenSC доступны следующие наборы параметров:

  • GOSTR3410-2012-512:A, id-tc26-gost-3410-12-512-paramSetA, OID 1.2.643.7.1.2.1.2.1, «ГОСТ Р 34.10-2012, 512 бит, параметры по умолчанию»
  • GOSTR3410-2012-512:B, id-tc26-gost-3410-12-512-paramSetB, OID 1.2.643.7.1.2.1.2.2, «ГОСТ Р 34.10-2012, 512 бит, параметры ТК-26, набор B»
  • GOSTR3410-2012-512:C, id-tc26-gost-3410-12-512-paramSetC, OID 1.2.643.7.1.2.1.2.3, «ГОСТ Р 34.10-2012, 512 бит, параметры ТК-26, набор С»

OpenSC не умеет читать (экспортировать) открытые ключи этого алгоритма.

Генерация секретного ключа на устройстве (AES, DES3, ГОСТ 28147-89)

Генерируем секретный ключ AES 128 бит на токене JaCarta PKI:

::shell-session
$ pkcs11-tool --module jcPKCS11-2 --slot-index 1 --login --pin 11111111 --keygen --key-type aes:16 --id 7 \
  --label 'AES demo key' --sensitive
Using slot with index 1 (0x2ffff)
Key generated:
Secret Key Object; AES length 16
  label:      AES demo key
  ID:         07
  Usage:      encrypt, decrypt, wrap, unwrap
  Access:     sensitive, extractable, local

Мы на всякий случай указываем аргумент --sensitive, чтобы защитить секретный ключ от извлечения. Без него данные ключа можно экспортировать в открытом виде.

Создание запроса на выпуск сертификата

Запрос на выпуск сертификата (certificate signing request, CSR) сделать средствами только pkcs11-tool невозможно, для этого нужно использовать внешнюю программу, например, openssl, однако эта операция весьма нетривиальная и требует кучу дополнительных манипуляций. Этот рецепт работает только в linux и требует дополнительно установленного пакета libengine-pkcs11-openssl:

::shell-session
$ sudo apt install libengine-pkcs11-openssl

Рассмотрим на примере рутокен ecp. Сначала сгенерируем на нём пару ключей RSA с меткой demo-rsa:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --keypairgen --key-type RSA:2048 --label demo-rsa

Теперь нам нужно для закрытого ключа с этой меткой выпустить CSR. Пакет libengine-pkcs11-openssl добавляет в openssl поддержку PKCS#11, в частности, OpenSC. Все параметры нужно задавать через конфигурационный файл openssl-pkcs11.cnf, вот его содержимое:

.include /etc/ssl/openssl.cnf

[default_conf]
engines = engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
MODULE_PATH = librtpkcs11ecp.so

В атрибуте MODULE_PATH мы должны указать такое же значение, какое указываем в аргументе --module, этот файл нужно редактировать для каждого модуля. Теперь у нас есть всё для генерации CSR (вводим пин токена и получаем CSR в файле csr.pem):

::shell-session
$ openssl req -new -config openssl-pkcs11.cnf -subj '/CN=test/' -sha256 -engine pkcs11 \
  -keyform engine -key 'slot_0-label_demo-rsa' -out csr.pem
engine "pkcs11" set.
Enter PKCS#11 token PIN for Rutoken ECP <no label>:

Для указания openssl, откуда брать ключ, мы указываем аргументы -engine pkcs11 -keyform engine, а для идентификации ключа используется специальный формат slot_SLOT_NUMBER-label_LABEL, где SLOT_NUMBER и LABEL — номер слота и метка объекта соответственно.

❈ ❈ ❈

Полученный CSR необходимо теперь отправить в удостоверяющий центр, где на его основе будет выписан сертификат. Для демонстрации выпишем сертификат самостоятельно. Подробно об этом я рассказываю в статье Ещё больше и лучше о цифровых сертификатах: X.509, PKI, PKCS, а здесь сразу приведу готовые команды без объяснений.

Сначала создаём ключ и сертификат «удостоверяющего центра»:

::shell-session
$ openssl ecparam -name secp384r1 -genkey -out demo-root-ca.key
$ openssl req -new -x509 -batch -days 1000 -key demo-root-ca.key -subj '/C=AQ/O=Penguin Co./CN=Demo Root CA' \
 -out demo-root-ca.crt

И генерируем сертификат на основе ранее созданного запроса:

::shell-session
$ openssl x509 -req -in csr.pem -days 365 -CA demo-root-ca.crt -CAkey demo-root-ca.key -CAcreateserial -out cert.pem

Импорт сертификата на устройство

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

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --type cert --write-object cert.pem --label demo-rsa
Created certificate:
Certificate Object; type = X.509 cert
  label:      demo-rsa
  subject:    DN: CN=test

Создание подписи файла закрытым ключом на устройстве

Рассмотрим создание цифровой подписи на примере ключа алгоритма ГОСТ Р 34.10-2012 с ID=9 и алгоритма хеш-функции ГОСТ Р 34.11-2012 с размером хеш-кода 512 бит, который мы создали выше на рутокен ECP. Создадим тестовый файл и сгенерируем подпись для него (при подписывании нужен логин, так как эта процедура выполняется при помощи закрытого ключа):

::shell-session
$ echo 'sample file to sign' > /tmp/test-file.txt
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --sign --id 09 \
  --mechanism GOSTR3410-WITH-GOSTR3411-12-512 --input-file /tmp/test-file.txt --output-file /tmp/test-file.txt.sig

Мы указываем механизм операции в аргументе --mechanism GOSTR3410-WITH-GOSTR3411-12-512, он должен присутствовать в выводе pkcs11-tool --list-mechanism.

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

Проверим подпись, созданную в прошлом сценарии:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --verify --id 09 --mechanism GOSTR3410-WITH-GOSTR3411-12-512 \
  --input-file /tmp/test-file.txt --signature-file /tmp/test-file.txt.sig
Using slot 0 with a present token (0x0)
Using signature algorithm GOSTR3410-WITH-GOSTR3411-12-512
Signature is valid

Для проверки подписи логин не нужен, так как эта операция выполняется при помощи открытого ключа.

Шифрование и дешифрование данных секретным AES-ключом на устройстве

Текущая версия OpenSC (0.22.0) не умеет работать с аппаратной реализацией симметричных алгоритмов, однако в версии 0.23 запланирована поддержка AES.

Шифрование и дешифрование данных секретным ключом ГОСТ 28147-89 на устройстве

Средствами OpenSC/pkcs11-tool это пока невозможно.

Изменение PIN

Пин токена можно изменить такой командой:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --login --pin 12345678 --change-pin --new-pin 12341234
Using slot 0 with a present token (0x0)
PIN successfully changed

Создание криптографического дайджеста файла

Допустим, у нас есть файл test.txt, мы хотим подсчитать его дайджест (хеш) по алгоритму SHA256 для программного токена SoftHSM:

::shell-session
$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --hash --mechanism SHA256 -i test.txt -o test.txt.sha256
Using slot 0 with a present token (0x47060dbd)
Using digest algorithm SHA256

Или по алгоритму ГОСТ Р 34-11.94, используя токен в первом слоте JaCarta:

::shell-session
$ pkcs11-tool --module /Applications/JaCartaUC.app/Contents/MacOS/jcPKCS11-2 --slot-index 0 --hash \
    --mechanism GOSTR3411 --input-file test.txt --output-file test.txt.gostr3411

Или по алгоритму ГОСТ Р 34-11.2012 («Стрибог») длиной 256 бит через рутокен ECP:

::shell-session
$ pkcs11-tool --module librtpkcs11ecp.so --hash --mechanism GOSTR3411-12-256 -i test.txt -o test.txt.gostr3411-2012-256
Using slot 0 with a present token (0x0)
Using digest algorithm GOSTR3411-12-256

❈ ❈ ❈

Дайджест всегда генерируется в бинарном виде. Естественно, если устройство не поддерживает указанный механизм (как, например, рутокен lite), вы получите ошибку. Вы можете воспользоваться утилитой xxd из пакета xxd, чтобы распечатать содержимое в привычном виде. Вот пример, как это работает с алгоритмом MD5 на рутокен ECP:

::shell-session
$ echo 'this was a triumph' > /tmp/hash-test.txt
$ pkcs11-tool --module librtpkcs11ecp.so --hash --mechanism MD5 -i /tmp/hash-test.txt | xxd -p          
Using slot 0 with a present token (0x0)
Using digest algorithm MD5
0b6ca23117cd22dead3d2f72d679ae69
$ md5sum /tmp/hash-test.txt
0b6ca23117cd22dead3d2f72d679ae69  /tmp/hash-test.txt

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

RSA-ключ на токене можно использовать для аутентификации на SSH-сервере. Рассмотрим на примере Аладдин eToken.

Создаём на токене пару RSA-ключей с конкретным идентификатором, например, 19:

::shell-session
$ pkcs11-tool --module libeToken.dylib --login --pin 1234567890 --keypairgen --key-type RSA:2048 --id 19

Извлекаем открытый ключ из токена и конвертируем его в формат ssh-rsa (я не использую команду ssh-keygen -D, поскольку она возвращает все открытые ключи с токена, а нам нужен конкретный):

::shell-session
$ pkcs11-tool --module libeToken.dylib --type pubkey --read-object --id 19 --output-file /tmp/pubkey.der
$ openssl rsa -pubin -in /tmp/pubkey.der -inform DER -out /tmp/pubkey.pem
$ ssh-keygen -f /tmp/pubkey.pem -i -mPKCS8
ssh-rsa AAAAB3Nza.....NDAh

Полученный на последнем этапе ключ стандартным образом прописываем на ssh-сервере в файл ~/.ssh/authorized_keys.

При подключении к серверу указываем полный путь до библиотеки PKCS#11 в аргументе -I:

::shell-session
$ ssh -I /usr/local/lib/libeToken.dylib [email protected]
Enter PIN for 'etoken 72':
[sigsergv@host:~]%

Также можно указать путь до библиотеки в конфигурационном файле ~/.ssh/config, если вы им пользуетесь для подключения:

Host test
    Hostname 10.0.34.2
    PKCS11Provider /usr/local/lib/libeToken.dylib
    User sigsergv

Дополнительные полезные рецепты

Просмотр подключенных USB-устройств

В линуксе команда lsusb, для её работы нужно поставить пакет usbutils: sudo apt install usbutils

В макоси команда /usr/sbin/ioreg -p IOUSB -l -w 0

Включение алгоритмов ГОСТ в системном openssl

Установите пакет с библиотекой поддержки алгоритмов ГОСТ:

::shell-session
$ sudo apt install libengine-gost-openssl1.1

Для использования без правки системного конфига openssl.cnf можно просто добавлять аргумент -engine gost к нужным командам. Например, генерация закрытого ключа ГОСТ Р 34.10-2012:

::shell-session
$ openssl genpkey -engine gost -algorithm gost2012_256 -pkeyopt paramset:A -out gost-2012-key.pem

Чтобы алгоритмы ГОСТ были доступны во всех командах openssl, создайте файл /etc/ssl/gost.cnf со следующим содержимым:

[default_conf]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
engine_id = gost
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet

А затем в системный конфиг openssl /etc/ssl/openssl.cnf в самый конец добавьте такую строчку:

.include /etc/ssl/gost.cnf

После этого поддержка алгоритмов ГОСТ появится во всех командах, проверить можно так:

::shell-session
$ openssl ciphers | tr ':' '\n' | grep -i gost
GOST2012-GOST8912-GOST8912
GOST2001-GOST89-GOST89
::shell-session
$ openssl engine
(dynamic) Dynamic engine loading support
(gost) Reference implementation of GOST engine

Ссылки и литература

Комментарии

Гость: Тельман | 2023-06-19 в 21:49

Спасибо большое за ваш труд! Первый раз наткнулся на ваши работы еще в 2019-ом, когда ковырял Mifare. Сейчас, как и в 2019-м, искал гайды в англоязычном сегменте, но качественный материал нашел у вас.

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