Openssl с поддержкой гост 2012 для windows

Gost 2012 engine OpenSSL compiled for Windows 32. Contribute to korser1/gostenginessl development by creating an account on GitHub.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

2
branches

0
tags

Code

  • Use Git or checkout with SVN using the web URL.

  • Open with GitHub Desktop

  • Download ZIP

Latest commit

Files

Permalink

Failed to load latest commit information.

Type

Name

Latest commit message

Commit time

gostenginessl

Gost 2012 engine OpenSSL compiled for Windows 32

Use it with Openssl 1.1.0g https://slproweb.com/products/Win32OpenSSL.html

add gost.dll to the bin dir of OpenSSL

at the start of openssl.cfg add:
openssl_conf = openssl_def

at the end openssl.cfg add:
[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

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

Today, 4th Февраль 2023, Ukraine is still bravely fighting for democratic values, human rights and peace in whole world. Russians ruthlessly kill all civilians in Ukraine including childs and destroy their cities.
We are uniting against Putin’s invasion and violence, in support of the people in Ukraine. You can help by donating to Ukrainian’s army.

Есть

1 Сертифиакт с контейнером закрытого ключа(header.key, masks.key, masks2.key, name.key, primary.key, primary2.key)

2. Он с поддержкой ГОСТ шифрования (2001 и 2012)

Чего хочется

хочу создать файл закрытого ключа (в формате RSA или PEM) и подписывать командами OPENSSL

Краткий план

  1. Нужно установить исходный сертификат (я использовала КриптоПРО)
  2. Выгружаем сертификат в формате pfx

Используем программу P12FromGostCSP, для получения контйнера PKCS#12

Дальше обновим openssl до версии > 1.1.1 и настроим на поддержку

  1. ГОСТ
  2. Теперь можем конвертировать, к примеру в pem

Настройка системы

важно!: для работы с GOST2012, версия openssl >=1.1.1

# источник (https://gist.github.com/shadz3rg/7badec13e154751116a6446fe9f61906)
# Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-36-generic x86_64)
# (из коробки) OpenSSL 1.1.0g  2 Nov 2017
# (из коробки) curl 7.58.0 (x86_64-pc-linux-gnu)
# PHP 7.2.10-0ubuntu0.18.04.1 (cli) (built: Sep 13 2018 13:45:02) ( NTS )

# Компилим GOST-engine
sudo apt install cmake libssl-dev
git clone --branch=openssl_1_1_0 https://github.com/gost-engine/engine.git gost-engine/engine
cd gost-engine/engine
cmake .
make

# узнаем нужную директорию, копируем туда
openssl version -e
cp bin/gost.so /usr/lib/x86_64-linux-gnu/engines-1.1

# конфиг
cp /etc/ssl/openssl.cnf /etc/ssl/openssl_custom.cnf
nano /etc/ssl/openssl_custom.cnf

# в начало файла
openssl_conf = openssl_def

# в конец
[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

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

# включаем новый конфиг
export OPENSSL_CONF=/etc/ssl/openssl_custom.cnf

openssl s_client -connect service.rosminzdrav.ru:443
curl https://service.rosminzdrav.ru

Проверка поддержки ГОСТ

командой:

openssl engine

результат:

SUSE:/root # openssl engine (dynamic) Dynamic engine loading support
(gost) Reference implementation of GOST engine

посмотреть есть ли ГОСТ шифры

openssl ciphers|tr ':' 'n'|grep GOST

GOST2001-GOST89-GOST89
GOST94-GOST89-GOST89

Команды конвертации openssl

Результат работы утилиты P12FromGostCSP, должен содержать сертификат и закрытый ключ. Проверить это можно командой:

openssl.exe pkcs12 -in C:/key.pfx -nodes

Для преобразования контейнера в формат pem можно воспользоваться командой:

 openssl.exe pkcs12 -in C:/key.pfx -out C:/key.pem -nodes -clcerts

или

openssl pkcs12 -in path.p12 -out newfile.crt.pem -clcerts -nokeys
openssl pkcs12 -in path.p12 -out newfile.key.pem -nocerts -nodes

о командах openssl

Извление данных из контейнера

Извлечения Закрытого ключа из контейнера PFX:

openssl pkcs12 -in container.pfx -nocerts -out key2019.pem –nodes

или

openssl pkcs12 -nodes -in dev-with- cert.pfx -nocerts -out private.key

Извлечения файла сертификата из контейнера PFX:

openssl pkcs12 -in container.pfx -nokeys -out cert2019.pem

или

openssl pkcs12 -nokeys -in dev-with-priv.pfx -out cert.pem

Удаление парольной фразы из контейнера PFX:

openssl rsa -in key2017.pem -out serverkey2019.key

Просмотр содержимого private key:

openssl pkcs12 -in test_file.pfx -passin pass:{пароль} -nocerts -nodes

Сборка контейнера PFX:

openssl pkcs12 -export -out container.pfx -inkey serverkey2019.key -in cert2019.pem -certfile CA.crt

We can extract the private key form a PFX to a PEM file with this command:

openssl pkcs12 -in filename.pfx -nocerts -out key.pem

Exporting the certificate only:

openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem

Removing the password from the extracted private key:

openssl rsa -in key.pem -out server.key

Ссылки

  • http://big-town.narod.ru/openssl.html
  • https://gist.github.com/shadz3rg/7badec13e154751116a6446fe9f61906

Не поделитесь инструкцией по сабжу?

Исходники OpenSSL беру отсюда, версия 1.1.1c.

engine беру отсюда (пакет cprocsp-cpopenssl-~11315-5.x86_64.rpm, в нем есть библиотека libgost.so, а это вроде бы именно то, что нужно).

Собираю так: ./config no-shared zlib —prefix=/opt/gostssl

Собирается успешно, OpenSSL запускается и показывает, что поддержка engine есть:

# openssl engine
(dynamic) Dynamic engine loading support

Но как только я пытаюсь подключить engine:

openssl_conf = openssl_def

[openssl_def]
engines = engine_section

[engine_section]
gostengy = gost_section

[gost_section]
engine_id = gostengy
dynamic_path = /opt/gostssl/lib/engines-1.1/libgost.so
default_algorithms = CIPHERS, DIGESTS, PKEY, PKEY_CRYPTO, PKEY_ASN1

то при запуске OpenSSL тут же получаю сообщение, что он не может загрузить so, возможно как раз потому, что я собирал OpenSSL со статической линковкой (без shared libs).

Но если я собираю OpenSSL так: ./config shared zlib —prefix=/opt/gostssl

то он собирается, но при запуске пишет, что error while loading shared libraries: libssl.so.1.1.

Эта библиотека в /opt/gostssl/lib/ (как она сама, так и симлинк libssl.so), но видимо OpenSSL пытается искать ее где-то в другом месте, скорее всего в общесистемном.

# ldd openssl 
        linux-vdso.so.1 =>  (0x00007fff43fff000)
        libssl.so.1.1 => not found
        libcrypto.so.1.1 => not found
        libz.so.1 => /lib64/libz.so.1 (0x00007fa234b42000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fa23493e000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa234720000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fa23438c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa234d61000)

Видимо путь нужно указывать где-то дополнительно.

На первый взгляд это похоже на баг, хотя и для бага указано, что он уже закрыт.

Кстати, по ссылке был предложен костыль, в виде добавления пути /opt/gostssl/lib в файле ld.so.conf.

Это помогло, теперь новая сборка OpenSSL запускается, но engine все равно не загружается:

# ./openssl engine
(dynamic) Dynamic engine loading support
140729665955584:error:25066067:DSO support routines:dlfcn_load:could not load the shared library:crypto/dso/dso_dlfcn.c:119:filename(/opt/gostssl/lib/engines-1.1/libgost.so): libcrypto.so.1.0.0: cannot open shared object file: No such file or directory
140729665955584:error:25070067:DSO support routines:DSO_load:could not load the shared library:crypto/dso/dso_lib.c:162:
140729665955584:error:260B6084:engine routines:dynamic_load:dso not found:crypto/engine/eng_dyn.c:414:
140729665955584:error:260BC066:engine routines:int_engine_configure:engine configuration error:crypto/engine/eng_cnf.c:141:section=gost_section, name=dynamic_path, value=/opt/gostssl/lib/engines-1.1/libgost.so
140729665955584:error:0E07606D:configuration file routines:module_run:module initialization error:crypto/conf/conf_mod.c:177:module=engines, value=engine_section, retcode=-1 

ВНИМАНИЕ! Это устаревшая инструкция!
Вместо openssl+gostengy/gost_capi надо использовать легализованный в КриптоПро CSP 5.0 R2 патч на nginx:
https://www.cryptopro.ru…sp/tls/gost-nginx-apache
https://support.cryptopr…-c-podderzhkojj-gost-tls

FAQ (обновлено 14 августа 2018)

Что такое gostengy и gost_capi?

gostengy и gost_capi — это библиотеки для OpenSSL, которые обеспечивают поддержку ключей и алгоритмов ГОСТ через вызовы КриптоПро CSP

В терминах OpenSSL, данные библиотеки — это криптографические модули, ENGINE

Какая разница между gostengy и gost_capi?

gostengy для OpenSSL >= 1.1.0, поддерживает ГОСТ 2012

gost_capi для OpenSSL от 1.0.0 до 1.0.2, НЕ поддерживает ГОСТ 2012

Какие требования gostengy и gost_capi?

Наличие КриптоПро CSP и OpenSSL

При использовании в nginx в Linux системах, желательно использовать вариант КС2 (так как nginx использует fork для дочерних процессов).

При использовании антивирусов, убедитесь в поддержке ГОСТ алгоритмов при фильтрации HTTPS или добавьте соответствующие исключения.

Каков процесс развертывания gostengy и gost_capi?

Как сконфигурировать OpenSSL?

Пример подключения gostengy через конфигурационный файл OpenSSL (обычно вставляется после «oid_section = new_oids»):

Код:

openssl_conf = openssl_def

[openssl_def]
engines = engine_section

[engine_section]
gostengy = gost_section

[gost_section]
engine_id = gostengy
dynamic_path = /path/to/dll/or/so/gostengy.dll
default_algorithms = CIPHERS, DIGESTS, PKEY, PKEY_CRYPTO, PKEY_ASN1

Пример подключения gost_capi:

Как проверить работоспособность OpenSSL с gostengy или gost_capi?

Проверить, что ENGINE загружается:

Пример вывода:

Цитата:

(dynamic) Dynamic engine loading support
(gostengy) CryptoPro GostEngy ($Revision: 168568 $)

Проверить возможность подписи (должно выполниться без ошибок):

Код:

openssl cms -sign -engine gostengy -keyform ENGINE -inkey www.example.com -in "doc.txt" -out "doc.signed.txt" -outform PEM -CAfile /path/to/cert/www.example.com.cer -nodetach -signer /path/to/cert/www.example.com.cer

Какие операционные системы поддерживает gostengy и gost_capi?

На текущий момент поддерживаются x86 и x64 системы семейства Linux и Windows

Для чего может быть использован gostengy и gost_capi?

gostengy в составе OpenSSL может быть использован для широкого круга задач, требующих поддержки ключей и алгоритмов ГОСТ, например для реализации защищенных SSL/TLS соединений в HTTP серверах, поддерживающих загрузку ключей из OpenSSL ENGINE, например nginx, и прочие варианты применения OpenSSL.

Какие версии TLS поддерживаются?

Для OpenSSL >= 1.1.0 поддерживаются версии TLS до 1.2 (рекомендуем использовать openssl-1.1.0-gost)

Для OpenSSL от 1.0.0 до 1.0.2 поддерживается TLS 1.0 (при использовании openssl-1.0.2-gost до TLS 1.2 включительно)

Какие версии nginx поддерживаются?

Начиная с 1.7.9 возможно использовать наш криптографический модуль;
Начиная с 1.11.0 возможно использовать одновременную работу ГОСТ и RSA сертификатов.

Как сконфигурировать nginx?

Конфигурация nginx для работы с ГОСТ происходит согласно документации с некоторыми нюансами:

  • Пользователь рабочих потоков nginx не должен отличаться от пользователя запускающего nginx (см. user)
  • Для сервера должен быть включен ssl
  • Сертификат сервера конфигурируется директивой ssl_certificate
  • Ключ сертификата конфигурируется директивой ssl_certificate_key, но вместо файла указывается зарезервированное слово «engine:», после которого следует имя OpenSSL ENGINE, в нашем случае это «gostengy» или «gost_capi», далее следует зарезервированный символ ‘:’, за которым следует имя сертификата. Например для сертификата «www.example.com», значение ssl_certificate_key выглядело бы так: «engine:gostengy:www.example.com»
  • Остальные директивы могут быть использованы по умолчанию

Таким образом, простейшая конфигурация gostengy в nginx должна содержать:

Код:

ssl on;
ssl_certificate /path/to/cert/www.example.com.cer;
ssl_certificate_key engine:gost_capi:www.example.com;

Как сконфигурировать nginx?

Как настроить одновременную работу ГОСТ и RSA в nginx?

Начиная с версии 1.11.0 в nginx возможно использовать несколько сертификатов для сервера одновременно.

Для типичной работы ГОСТ TLS в nginx (сначала ГОСТ потом RSA), следует использовать приоритет шифросюит (сначала ГОСТ потом всё остальное), например так:

Код:

ssl_ciphers GOST2012-GOST8912-GOST8912:GOST2001-GOST89-GOST89:HIGH;

Можно ли использовать контейнеры без сертификатов в качестве ключей в gostengy?

Можно ли использовать gostengy или gost_capi в качестве прокси-сервера в nginx?

Как сконфигурировать Apache httpd?

К сожалению нам не удалось включить изменения позволяющие работать в официальный репозиторий Apache httpd, конкретно в mod_ssl (историю рассмотрения патча можно посмотреть здесь).

Однако, вы можете самостоятельно собрать mod_ssl с нашим патчем: mod_ssl_gost_capi.zip (2kb) загружен 122 раз(а).

Или воспользоваться репозиторием с патчем: https://github.com/deemru/httpd

Настройка по смыслу аналогична настройке nginx, только вместо ssl_certificate_key в nginx используется SSLCertificateKeyFile в Apache.

Как сконфигурировать Apache httpd по шагам?

Какая лицензия используется gostengy и gost_capi?

Использование серверных сертификатов требует наличия серверной лицензии у CSP

Как получить gostengy и gost_capi?

Отредактировано модератором 27 июля 2021 г. 14:14:56(UTC)
 | Причина: обновление FAQ

Содержание

  • 1 Применимость
  • 2 Установка и настройка
  • 3 Формирование запроса на сертификат с поддержкой алгоритма ГОСТ (пример)
  • 4 Получение контрольной суммы используя алгоритмы ГОСТ
  • 5 Для 32-разрядных систем

Применимость

  • Приведённая ниже инструкция актуальна для RED X3|X4 и FRESH R8.1|R11. Реализация OpenSSL в этих дистрибутивах включает поддержку алгоритмов ГОСТ
  • Наличие в ОС реализации алгоритма ГОСТ не означает автоматического наличия сертификата регулятора на эту реализацию. Проверка контроля встраивания не производилась, сертификат регулятора (ФСБ РФ) на эту реализацию отсутствует. Таким образом, применять эту реализацию можно только в целях осуществления проверок функционирования, либо в соответствии со статьей 1, пункт 2, подпункт 1 152-ФЗ

Установка и настройка

По-умолчанию поддержка ГОСТ отключена. Активизируем поддержку алгоритма в конфигурационном файле:

  • Редактируем файл /etc/pki/tls/openssl.cnf Вначале файла, прямо первой строкой определим дополнительную секцию openssl_conf=openssl_def, например:
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
openssl_conf=openssl_def
  • Затем в конец этого же файла вносим описание алгоритма в конфигурационный файл, с учетом верного пути к библиотеке, например:
[openssl_def]
engines = engine_section

# Engine scetion
[engine_section]
gost = gost_section

# Engine gost section
[gost_section]
engine_id = gost
dynamic_path = /usr/lib64/openssl-1.0.0/engines/libgost.so   
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
  • Удостоверимся, что библиотека openssl корректно опознала добавленный алгоритм ГОСТ. Для этого выполним:
openssl  engine gost -c

Ответ системы будет такой:

(gost) Reference implementation of GOST engine
[gost89, gost89-cnt, gost89-cnt-12, gost89-cbc, md_gost94, gost-mac, md_gost12_256, md_gost12_512, gost-mac-12, gost2001, gost-mac, gost2012_256, gost2012_512, gost-mac-12]

Формирование запроса на сертификат с поддержкой алгоритма ГОСТ (пример)

openssl genrsa -out test.example.ru.key 2048
openssl req -new -sha256 -key test.example.ru.key -out test.example.ru.csr
openssl genpkey -algorithm gost2001 -pkeyopt paramset:A -out gost.example.ru.key
openssl req -engine gost -new -key gost.example.ru.key -out gost.example.ru.csr

Получение контрольной суммы используя алгоритмы ГОСТ

Для получения хэш-функции согласно ГОСТ Р 34.11-2012.

 openssl dgst -engine gost -md_gost12_256 <имяфайла>
 openssl dgst -engine gost -md_gost12_512 <имяфайла>

Для 32-разрядных систем

В случае с 32-разрядными системами стоит быть внимательнее с путями в файле настроек:
dynamic_path =/usr/lib/openssl-1.0.0/engines/libgost.so

Окружение

  • Версия РЕД ОС: 7.3.1
  • Конфигурация: Рабочая станция
  • Версия ПО: openssl-gost-engine-1.1.1.0-0

В состав дистрибутива РЕД ОС входит пакет библиотек, поддерживающих методы защитного преобразования по алгоритмам ГОСТ, — openssl-gost-engine.

Пакет openssl-gost-engine включает в себя реализацию следующих алгоритмов ГОСТ:

  • ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012 — алгоритмы электронной цифровой подписи.

  • ГОСТ Р 34.11-94 — Алгоритм хэширования. 256-битное значение хэша.

  • ГОСТ Р 34.11-2012 — Алгоритм хэширования. 256- и 512-битные значения хеша.

  • ГОСТ 28147-89 — Симметричное шифрование с 256-битным ключом. Доступны режимы CBC, CFB и CNT. Для усложнения статистического анализа поддерживается «key meshing» (подробнее см. RFC 4357).

  • ГОСТ 28147-89 в режиме выработки имитовставки (MAC). Основан на алгоритме хэширования с использованием алгоритмов симметричного шифрования. Он имеет 256-битный симметричный ключ и разрядность от 8 до 64 (по умолчанию 32) бит.

  • ГОСТ Р 34.13–2015 — Симметричное шифрование «Кузнечик» («Grasshopper»).

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

Для установки пакета openssl-gost-engine перейдите в сеанс пользователя root:

su -

и выполните команду:

dnf install openssl-gost-engine

Здесь и далее команды будут выполняться с правами пользователя root, если не указано иное.

Первый способ переключения на ГОСТ

После установки openssl поддержку алгоритмов ГОСТ можно включить следующей командой:

openssl-switch-config <gost | default>

При указании аргумента gost поддержка алгоритмов ГОСТ включается, при указании аргумента default — возвращаются настройки по умолчанию.

Второй способ переключения на ГОСТ

Отредактируйте файл настроек /etc/pki/tls/openssl.cnf:

1. В начало файла поместите строку:

openssl_conf = openssl_def

2. Закомментируйте настройки по умолчанию:

#openssl_conf = default_modules
#[ default_modules ]
#ssl_conf = ssl_module

#[ ssl_module ]
#system_default = crypto_policy

#[ crypto_policy ]
#.include = /etc/crypto-policies/back-ends/opensslcnf.config

3. В конец файла добавьте следующие строки:

[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
engine_id = gost dynamic_path = /usr/lib64/engines-1.1/gost.so
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet

4. Затем необходимо явно указать Cipher Strings в файле конфигурации /etc/crypto-policies/back-ends/openssl.config:

@SECLEVEL=1:aGOST:aGOST01:kGOST:GOST94:GOST89MAC:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8

Проверка, что OpenSSL может использовать алгоритмы ГОСТ

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

openssl ciphers | tr ":" "n" | grep GOST GOST2012-GOST8912-GOST8912 GOST2001-GOST89-GOST89 

Пример генерации ключей

Генерация закрытого ключа и создание сертификата с подписью ГОСТ производится следующей командой:

openssl req -x509 -newkey gost2012_256 -pkeyopt paramset:A -nodes -keyout key.pem -out cert.pem -md_gost12_256

Для проверки сертификата выполните команду:

openssl x509 -in cert.pem -text -noout 
 
Certificate:
    Dat a:
        Version: 3 (0x2)
        Serial Number:
            17:86:3c:c0:8c:62:36:af:88:3c:19:01:34:bb:19:92:61:38:5a:37
        Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
        Issuer: C = ru, ST = Russia, L = Moscow, O = red-soft, OU = drsp, CN = root, emailAddress = root
        Validity
            Not Before: Mar 15 11:24:48 2022 GMT
            Not After : Apr 14 11:24:48 2022 GMT
        Subject: C = ru, ST = Russia, L = Moscow, O = red-soft, OU = drsp, CN = root, emailAddress = root
        Subject Public Key Info:
            Public Key Algorithm: GOST R 34.10-2012 with 256 bit modulus
                Public key:
                   X:27F4547D48EFAAE904FDCDCD190EB702858B77A796600E175FDEDA8BA35E3C1A
                   Y:35D4E769099EDBC4461A8E67510897D98FD59C4F4D34F08F722899EAD7ABEF81
                Parameter set: id-GostR3410-2001-CryptoPro-A-ParamSet
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                4B:E5:69:DE:B5:00:AE:01:71:56:97:C8:C5:30:8C:B1:5F:5E:AF:AF
            X509v3 Authority Key Identifier: 
                keyid:4B:E5:69:DE:B5:00:AE:01:71:56:97:C8:C5:30:8C:B1:5F:5E:AF:AF

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
         3e:94:02:7d:82:7a:52:5c:4d:09:8b:ae:c9:51:c1:19:2a:0f:
         c9:ce:39:39:89:27:89:87:e2:e7:bf:f7:9a:b3:be:bd:56:ea:
         27:bf:56:d8:99:a9:96:09:62:a5:49:04:69:d1:ea:b3:0f:fa:
         92:04:6a:da:27:79:49:ac:79:bd

Если вы нашли ошибку, пожалуйста, выделите текст и нажмите Ctrl+Enter.

Open source


Рекомендация: подборка платных и бесплатных курсов 3D-моделирования — https://katalog-kursov.ru/

В этой статье я расскажу о том, как я решал задачу об интеграции в тестовом режиме с сервисами, которые работают с использованием алгоритмов, определенных ГОСТ Р 34.10-2001 (устарел) и ГОСТ Р 34.10-2012. Приведу примеры некоторых проблем, с которыми столкнулся при решении задачи, дам ссылки на готовое решение и покажу несколько примеров их использования.

Причины

Для начала стоит сказать, что для продакшн-окружения существуют сертифицированные средства от компаний «Криптоком», «Крипто-Про», «Сигнал-КОМ» и других. Мне же нужно было реализовать взаимодействие в тестовом (девелоперском) окружении на Linux, покупать для этого лицензии не очень-то удобно, но что хуже, в открытом доступе отсутствуют документации по этому вопросу. По запросу «https гост» не так много решений. Среди них упоминается использование OpenSSL + Крипто CSP, я не помню деталей, но эта связка у меня не завелась с поддержкой ГОСТ Р 34.10-2012. Другим результатом, который часто встречался, было предложение использовать OpenSSL 1.0, в котором GOST-engine встроен внутрь, но такое решение тоже не содержало в себе поддержку GOST2012-GOST8912-GOST8912.

Рабочим решением оказалась сборка OpenSSL 1.1.0g + вынесенный в отдельно подключаемый динамический движок GOST-engine. В интернете часто встречается упоминание, что некая российская компания приложила усилия по его разработке, но в самом репозитории нет сведений об авторах продукта. Пользуясь случаем, выражаю авторам благодарность за движок в open source. На этой странице сказано, что до OpenSSL 1.1.0 использовался встроенный движок GOST, сейчас для GOST используется сторонний от OpenSSL продукт. Судя по конфигурации, скорее всего, это одна и та же библиотека.

Сборка OpenSSL, GOST-engine, cURL

Сборка стороннего продукта для тех, кто делает это редко, может быть нетривиальной задачей. Для сборки OpenSSL, GOST-engine и cURL пришлось разобраться с кучей опций и перепробовать несколько комбинаций версий. Если в Dockerfile вы заметите странное, то, скорее всего, это осталось от таких экспериментов.

Я зафиксировал все версии проектов для сборки, чтобы исключить ситуацию, что из-за обновления что-то перестанет работать. Например, я собирал OpenSSL 1.1.0h + GOST-engine и команда openssl ciphers не содержала GOST-алгоритмов, хотя openssl engine показывала GOST-engine в списке. Указав предыдущую версию OpenSSL 1.1.0g, все работало, как ожидалось. Это было очень странно, я повторил это еще раз, потом пытался выяснить причины, но в итоге решил остаться на 1.1.0g.

Собирая сам GOST-engine, я не сразу обратил внимание на наличие файла INSTALL.md в master-ветке, потому что собирал из ветки openssl_1_1_0 по неизвестно откуда взятой документации. Та версия собиралась с кастомной сборкой OpenSSL командой

cmake -DCMAKE_C_FLAGS='-I/usr/local/ssl/include -L/usr/local/ssl/lib' ..

Но master-ветка так собираться перестала, появились ошибки об отсутствии DOPENSSL_ROOT_DIR и подобное. В итоге решение было найдено и зафиксировано.

Для сборки cURL с кастомной сборкой OpenSSL гораздо больше документации, тем не менее, документация успевала устаревать, и с опциями пришлось много экспериментировать.
Результат работы выложен здесь.
Образ запушен в Docker Hub.

Примеры использования OpenSSL + GOST-engine

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

docker run --rm -i -t rnix/openssl-gost bash

Для начала можно убедиться, что алгоритмы GOST2012-GOST8912-GOST8912 и GOST2001-GOST89-GOST89 есть в списке поддерживаемых:

openssl ciphers

Если вам известен хост, который работает по HTTPS на основе ГОСТ-алгоритмов, то посмотреть его сертификат и попробовать подключиться можно командой:

openssl s_client -connect gost.example.com:443 -showcerts

Создать закрытый ключ и сертификат по ГОСТ Р 34.10-2012:

openssl req -x509 -newkey gost2012_256 -pkeyopt paramset:A -nodes -keyout key.pem -out cert.pem

Подписать файл ранее созданными сертификатами:

openssl cms -sign -signer cert.pem -inkey key.pem -binary -in file.txt -nodetach -outform DER -nocerts -noattr -out signed.sgn

Извлечь содержимое подписанного файла, сертификатом, который был подписан самим собой:

openssl cms -verify -in signed.sgn -certfile cert.pem -CAfile cert.pem -inform der -out data.txt

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

Программа cURL в использовании не изменилась, просто поддерживает хосты с ГОСТ-сертификатами.

Использование образа в работе с языками программирования

Если язык программирования позволяет исполнять установленные в системе программы, то задача использования ГОСТ-алгоритмов проще всего решается копированием бинарников собранных openssl и curl в конце Dockerfile языка программирования с использованием multi-stage build. Например:

FROM rnix/openssl-gost AS openssl-gost

# Replace with any other image based on Debian x86_64
FROM debian:stretch-slim

COPY --from=openssl-gost /usr/local/ssl /usr/local/ssl
COPY --from=openssl-gost /usr/local/ssl/bin/openssl /usr/bin/openssl
COPY --from=openssl-gost /usr/local/curl /usr/local/curl
COPY --from=openssl-gost /usr/local/curl/bin/curl /usr/bin/curl
COPY --from=openssl-gost /usr/local/bin/gostsum /usr/local/bin/gostsum
COPY --from=openssl-gost /usr/local/bin/gost12sum /usr/local/bin/gost12sum

Даже необязательно копировать в /usr/bin, это можно сделать в любой каталог, а затем вызывать из вашей программы, передав полный путь и все аргументы.

Поддержка ГОСТ-алгоритмов в PHP

PHP, конечно, позволяет делать вызовы системных команд, используя, например, exec. Но, глядя на то, как собирается PHP-FPM в Dockerfile, мне показалось, что можно легко собрать PHP с кастомными сборками OpenSSL и cURL. Как оказалось дальше, я ошибся, что это легко. Всё равно собрал.

По какой-то причине, я начал с PHP-FPM 7.1. Идея была в том, чтобы использовать multi-stage build. Для этого надо заменить в их Dockerfile инструкцию FROM на мою FROM rnix/openssl-gost AS openssl-gost, затем прописать копирования собранных openssl и curl до начала сборки самого php и, наконец, указать в опции сборки путь до этих библиотек --with-openssl-dir=/usr/local/ssl и --with-curl=/usr/local/curl заменив оригинальные.

Сюрпризы ждали отовсюду. Одним из значительных было то, что при сборки php 7.1 используется pkg-config, а явная установка libcurl4-openssl-dev, libssl-dev прописывали в pkg-config версии из пакетов. В результате собиралось не то, что нужно. Если убрать их установку, то /configure php падал, ссылаясь на отсутствие openssl в pkg-config. Пришлось дополнительно копировать из кастомных сборок openssl и curl их lib/pkgconfig /*. После десятков таких сюрпризов сборка начала проходить. Дальше выяснилось, что зависимости устанавливали openssl, тем самым перезатирая ранее скопированный бинарник моей кастомной сборки. Пришлось дополнительно копировать его в самом конце. Но это не всё.

В собранном php появились алгоритмы хешей openssl_get_md_methods(): GOST R 34.11-2012 with 256 bit hash, GOST R 34.11-2012 with 512 bit hash, GOST R 34.11-94. Это значило, что php подключил GOST-engine. А вот использование расширения curl в php почему-то говорило, что таких алгоритмов не знает, соединяясь с хостом по GOST-HTTPS. Я потратил несколько часов, пытаясь найти причину этого. Я смотрел исходники, как устроено расширение curl в php, как устроен сам curl, как они связываются с openssl. Я искал место, где могут определяться поддерживаемые алгоритмы или подключатся движки. Я искал по master-веткам, много гуглил, но ничего, что решило бы сразу проблему, не нашел. Тогда я вспомнил, что я собираю не последнюю версию PHP.

Я попробовал собрать PHP-FPM 7.2. Пришлось внести некоторые правки в мой скрипт корректировки оригинального Dockerfile PHP-FPM, но сборка начала проходить без большого количества сюрпризов. Главной новостью стало то, что теперь расширение curl внутри php умело общаться по ГОСТ-алгоритмам с хостами, но была одна неприятность. Каждый вызов php писал в stdout GOST engine already loaded. Очень неприятно. Я не сразу понял, кто это делает, но такую строчку нашел в исходниках GOST-engine. Я до сих пор не знаю, в какой части системы случилась ошибка: php, php-curl, curl, openssl. Но, видимо, в php 7.1 php-curl не подключал движок совсем, теперь в php 7.2 начал подключать его дважды. Так как все работало корректно, только был вывод, я решил его убрать правкой исходника инструкцией в Dockerfile:

sed -i 's|printf("GOST engine already loaded\n");|goto end;|' gost_eng.c

Там строчкой ниже уже есть goto end;, поэтому ничего серьезного я не сделал. Зато, пересобрав весь зоопарк, все начало работать, как и хотелось.
Образ с PHP-FPM + OpenSSL + GOST + cURL запушен в Docker Hub.

Поддержка ГОСТ-сертификатов в nginx

Возможность работать из языков программирования это уже много, но хотелось еще две возможности:

  1. Легко поднимать свой веб-сервер с ГОСТ-сертификатом по HTTPS (TLS).
  2. Легко проксировать все запросы на хост с ГОСТ-сертификатом

Легко – это означает докер-образ. Его нужно создать. Для этого нужно в Dockerfile собрать nginx с кастомным OpenSSL и GOST-engine. Открыв документацию сборки nginx, я увидел одну опцию о ssl — --with-http_ssl_module, которая просто булева. Но nginx популярный продукт, инструкций по сборке с openssl много, поэтому я нашел еще опцию --with-openssl=[DIR]. Как показала практика, nginx хочет, чтобы здесь были исходники openssl, а сборкой скрипты nginx займутся сами. Это не совсем то, что я хотел бы (я хотел использовать multi-stage build). Я ознакомился с help-выводом сборщика nginx, но ничего, что мне там помогло бы, я не нашел.

Пришлось дублировать инструкции выкачивания исходников OpenSSL, распаковки, сборки GOST-engine, включения GOST-engine в конфиги. Всё это начало собираться, но поддержки ГОСТ-алгоритмов в nginx все ещё не было. Это я проверял указанием в конфиге ssl_ciphers GOST2001-GOST89-GOST89:HIGH:MEDIUM;. Выполнение nginx -t говорило, что не знает этого алгоритма.

Как оказалось, openssl, собранный nginx, не поддерживал динамические движки, т.е. ./Configure выводил no-dynamic-engine [forced]. Здесь пришлось внимательно почитать документацию сборки OpenSSL, чтобы выяснить, что проставило forced. Причина нашлась в аргументах сборки openssl, которые вызывал nginx, а именно no-shared. Если это указано, то нет никаких флагов, чтобы включить поддержку загрузки движков. Пришлось править инструкцию сборки:

sed -i 's|--prefix=$ngx_prefix no-shared|--prefix=$ngx_prefix|' auto/lib/openssl/make

Всё это собралось, но nginx начал ругаться, что не может найти gost.so по пути /usr/lib/x86_64-linux-gnu/, это довольно странно, потому что тот же собранный openssl ищет и находит движки совсем в другом месте, а именно там, где и собирался ./lib/engines-1.1. Добавил инструкцию копирования собранных движков в /usr/lib/x86_64-linux-gnu/, чтобы угодить nginx. Заработало.

Рядом с основным Dockerfile в репозитории я положил демонстрационный Dockerfile, который при сборке создает себе ГОСТ-сертификаты и использует их, обрабатывая соединения на https://gost.example.com. Придется поработать с DNS или docker network, чтобы из одного контейнера попробовать подключится к этому демонстрационному, но все это я описал в документации.
Демонстрационный хост использует ключи по gost2001, другие варианты это gost2012_256, gost2012_512. А вместо GOST2001-GOST89-GOST89GOST2012-GOST8912-GOST8912.
Образ с nginx + GOST запушен в Docker Hub: https://hub.docker.com/r/rnix/nginx-gost/

Заключение

Мной изучена проблема работы с ГОСТ-алгоритмами в системах Linux, предоставлено решение в виде docker-образов, все это сопровождено документацией и примерами. Решение оформлено в виде репозитория на GitHub.

Стоит сказать о безопасности использования такого решения. Главное, не стоит доверять образам на Docker Hub, даже если там написано Automated Build. Я все равно могу собрать образ с любыми правками всех используемых библиотек и систем и запушить его в свой Docker Hub под любым тегом. Поэтому рекомендую форкать репозиторий на гитхабе, пулить его себе и уже самостоятельно собирать, проверив инструкции в Dockerfile на наличие того, что используются только официальные ресурсы без подозрительных модификацией по ходу сборки.

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

Ссылки

  1. Репозиторий со всеми решениями на GitHub
  2. Образ на Docker Hub с OpenSSL + GOST + cURL
  3. ГОСТ Р 34.10-2012 на Википедии со списком сертифицированных решений
  4. Репозиторий GOST-engine
  5. О возможностях и ограничениях GOST-engine
  6. Пример того, как решают вопрос в продакшн-окружении

Понравилась статья? Поделить с друзьями:
  • Openssl не является внутренней или внешней командой windows
  • Openssl для windows 10 x64 скачать
  • Openssl windows 64 скачать на русском
  • Openssl shared library для windows 10
  • Openssh windows server 2012 r2 настройка