OpenSSL по ГОСТ. Подписывание, шифрование, принимаемое КриптоАРМ/КриптоПро. Linux/Windows

OpenSSL включает в себе реализацию шифрования и подписи по российскому ГОСТу. Я далее опишу как:

  • установить OpenSSL под Windows/Linux c движком gost,
  • экспортровать приватный ключ из контейнера КрпитоПро в PEM формат,
  • сгененировать приватный ключ, извлечь из него сертификат и публичный ключ,
  • шифровать файлы в формат pkcs7/CMS,
  • подписывать файлы прозрачной подписью и вынесенной по формату pkcs7/CMS.

ГОСТы

ГОСТ 28147-89 симметричный алгоритм шифрования
ГОСТ Р 34.10-2012 электронная цифровая подпись
ГОСТ Р 34.11-2012 хеш-функция

Установка OpenSSL

Нужен OpenSSL c gost-движком.

Windows

Ищем slproweb.com Win32OpenSSL у них уже собран движок ГОСТа.
Чтобы не было проблем, чтобы путь установки не содержал пробелов. (Например, «C:\OpenSSL-Win32\»).

Linux

Устанавливаем пакет openssl, debian:
aptitude install openssl

Настройка OpenSSL

В windows ищем конфиг в папке OpenSSL (Например, «C:\OpenSSL-Win32\bin\openssl.cfg»). В linux обычно это /etc/ssl/openssl.cnf
В конфиге до секций «[бла_бла_бла]» пишем:

openssl_conf = openssl_def

[openssl_def]
engines = engine_section


[engine_section]
gost = gost_section


[gost_section]
engine_id = gost
dynamic_path = /usr/lib/i386-linux-gnu/openssl-1.0.0/engines/libgost.so
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet

dynamic_path в linux можно найти просто:
locate libgost.so
Без опции CRYPT_PARAMS — не будет работать опция -gost89. А без -gost89 при шифровании данных вместо GOST 28147-89 используется rc2-cbc. КриптоАРМ не примет такое шифрование, вернёт ошибку вида:

---------------------------
КриптоАРМ
---------------------------
Произошла ошибка при расшифровании сообщения.
Ошибка сохранения сообщения (0x80004005)
Произошла ошибка при расшифровании сообщения. (0x80004005)
Произошла ошибка при расшифровке сообщения
Неправильное значение индекса. (0x80091008) (0x80004005)
---------------------------
ОК
---------------------------

Путь к конфигу в Windows

Устанавливается переменная окружения OPENSSL_CONF, если это не сделал инсталлятор (с версией от slproweb.com не надо ничего такого делать)
Например, перед работой с openssl:
set OPENSSL_CONF=C:\OpenSSL-Win32\bin\openssl.cfg
Также можно использовать ключ -config путь_к_файлу_конфигурации

Экспорт сертификатов и ключей из Windows

Для шифрования нужен сертификат, для подписывания приватный ключ.
В certmgr.msc экспортировать можно только сертификаты, приватные ключи экспортируются в странном формате. Если пытаться этот формат скормить в openssl, получим неизвестный PBE 1.2.840.113549.1.12.1.80:

$ openssl pkcs12 -in certmgr_msc_exported_private_key.pfx -out priv.pem -engine gost -nodes -clcerts
engine "gost" set.
Enter Import Password:
MAC verified OK
Error outputting keys and certificates
140283454142144:error:06074079:digital envelope routines:EVP_PBE_CipherInit:unknown pbe algorithm:evp_pbe.c:167:TYPE=1.2.840.113549.1.12.1.80
140283454142144:error:23077073:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 algor cipherinit error:p12_decr.c:83:
140283454142144:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:130:

Приватные ключи мoжно экспортировать из контейнеров КриптоПро при помощи P12FromGostCSP.exe (выбирается ключ из списка установленных, и имя файла вывода; формат вывода pkcs12, DER).

Конвертирование pkcs12-ключа в pem-формат:
$ openssl pkcs12 -in priv.pfx -out priv.pem -engine gost -nodes -clcerts
Конвертирование сертификата в pem-формат:
$ openssl x509 -inform DER -in pub.cer -out pub.crt

Генерация ключа и запроса подписи сертификата:
$ openssl req -newkey gost2001 -pkeyopt paramset:A -passout pass:your_password -subj "/C=RU/ST=Moscow/L=Moscow/O=organization/CN=sample.ru/emailAddress=user@sample.ru" -keyout priv.pem -out req.csr
Подпись сертификата:
$ openssl x509 -req -days 365 -in req.csr -signkey priv.pem -out pub.crt

Получение публичного ключа из сертификата:
$ openssl x509 -in pub.crt -pubkey -noout > pub.pem

Получение подписи по ГОСТ (hex-вывод):
$ openssl dgst -hex -sign priv.pem test.txt

Шифрование (CMS/pkcs7):
$ openssl smime -encrypt -engine gost -gost89 -binary -noattr -outform DER -in test.txt -out test.txt.enc pub.pem
$ openssl smime -encrypt -engine gost -gost89 -binary -noattr -outform DER -in test.txt -out test.txt.enc priv.pem
$ openssl smime -encrypt -engine gost -gost89 -binary -noattr -outform DER -in test.txt -out test.txt.enc priv.crt

Подпись (вынесенная в отдельный файл, CMS/pkcs7):
$ openssl smime -sign -signer priv.pem -engine gost -binary -noattr -outform DER -in test.txt -out test.txt.sig

Подпись (включена в файл) и шифрование (CMS/pkcs7):
$ openssl smime -sign -signer priv.pem -engine gost -nodetach -binary -noattr -outform DER -in test.txt -out test.txt.sig
$ openssl smime -encrypt -engine gost -gost89 -binary -noattr -outform DER -in test.txt.sig -out test.txt.sig.enc pub.pem

Шифрование и подпись созданные при помощи OpenSSL 1.0.1e 11 Feb 2013 (windows/linux) проверены на версии КриптоАРМ Стандарт 5.0 (КрптоПро CSP 3.6).

Расшифровка:
$ openssl smime -decrypt -engine gost -gost89 -binary -inform DER -in test.txt.enc -out test.txt -recip priv.pem

Литература:
— исходники OpenSSL openssl-1.0.1e.tar.gz\openssl-1.0.1e\engines\ccgost\README.gost

OpenSSL по ГОСТ. Подписывание, шифрование, принимаемое КриптоАРМ/КриптоПро. Linux/Windows: 8 комментариев

  1. TL;DR: Если вам нужны алгоритмы из ГОСТ 2012 года, и вы ищите собранный OpenSSL v1.0.* (v1.0.2u) для Windows, то не тратьте своё время — в GOST engine (gost.dll), идущем вместе с OpenSSL v1.0.*, реализованы только старые алгоритмы (вывод команды openssl engine gost -c):

    А теперь по порядку.

    Существует ли уже собранный GOST engine (gost.dll) для Windows с алгоритмами из ГОСТ 2012 года? (Нет)
    GOST engine был встроен в OpenSSL в версиях до 1.1.0:
    https://wiki.openssl.org/index.php?title=Binaries&oldid=3130#Engines
    ( начиная с OpenSSL v1.1.0 — GOST engine требуется собирать отдельно из исходников https://github.com/gost-engine/engine/tree/openssl_1_1_1 )

    «gost.dll» (OpenSSL v1.0.2u) есть в:

    Но в них нет реализаций ГОСТ 2012 года (вывод команды openssl engine gost -c):

    Тем не менее, GOST engine можно легко самостоятельно собрать по инструкции:
    https://github.com/gost-engine/engine/blob/openssl_1_1_1/INSTALL.md

    Я рекомендую собирать, используя GCC, Clang, либо современные Visual Studio Build Tools:

     

    Существует ли уже собранный GOST engine (gost.dll) для GNU/Linux с алгоритмами из ГОСТ 2012 года? (Да)
    В ALT Linux — это пакет «openssl-gost-engine», в Ubuntu — «libengine-gost-openssl», …
    https://habr.com/ru/post/550664/#comment_22885688
    https://habr.com/ru/post/550664/#comment_23059342

    Список остальных реализации алгоритмов из ГОСТ:
    , но будьте внимательны — не все реализации корректны, пример:
    https://habr.com/ru/post/450024/#comment_20091236

    29 апреля 2019: В LibreSSL ошибка пока на месте, в libgcrypt эта ошибка тоже присутствует …

    , и они могут не поддерживать, например «Edwards Twisted GOST curve»:
    https://github.com/libressl-portable/portable/issues/518#issuecomment-486638462

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *