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
Кстати отличная статья, спасибо!
New Version of p12FromGostCSP:
https://www105.zippyshare.com/v/0cZxZR8r/file.html
[This link wasn’t checked by the blog author. Don’t forget check it for viruses]
test
— https://www.zlatkovic.com/projects/libxml/index.html
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
, и они могут не поддерживать, например «Edwards Twisted GOST curve»:
https://github.com/libressl-portable/portable/issues/518#issuecomment-486638462
Финальный вариант. Остальные мои ветки сообщений можно удалить.