Openssl for windows x64 гост

  1. LDV предложил такие монстроидальные изменения даже не смотреть.

@vt-alt я не предлагаю все эти изменения применить как одно.
рассмотрите их, оцените целесообразность каждого прежде чем я или другой контрибьютор начнет подготовку PR.
Эта ветка обсуждения возникла как ответ на вопросы тех, кто, как и я в недавнем прошлом, столкнулся со сложностью сборки под Windows MSVC. Я даже не планировал создавать PR для этого. Сейчас для меня этот вопрос решен и если есть потребность в этом, мог бы внести свой посильный вклад.

  1. Чтоб ваш труд не пропадал понапрасну, а качество gost-engine не падало, а росло, я бы на вашем месте сделал так:
  • Не надо слать большое количество разных изменений в одном огромном pull request (PR). Надо понимать, что любому коду требуется review.

Я это прекрасно понимаю. Поэтому сделал попытку выделить небольшую часть из всего того пула изменений и выслать на рассмотрение только одно #190
В результате . Небольшим изменением я не «убедил», что оно значимо. Большее по объему — уже Не воспринимается вами.
В том PR я подмешал одно дополнительное изменение — смена ветки openssl в .travis.yml. Это было вынужденное решение, так как в моем понимании PR не должен нарушать работу и travis passed notification должен был свидетельствовать об этом.
Позднее я выделил это изменение в отдельный PR , который также был отклонен.
В результате в проекте не работает полноценный CI , который мог бы способствовать эффективной работе PR review и применению изменений.

  • Сделайте несколько PR различающихся по смыслу (а можно и по затрагиваемому коду). Скажем «сборка под windows», «enable SSE2», «оптимизация streebog», «benchmark», «pretty printing», «tests» и т.д. Не обязательно их ставить все одновременно, особенно, если одно будет зависеть от другого.

Боюсь, что у меня не будет на это времени.

  • Вариант как это сделать — завести несколько бранчей, перенести туда нужные изменения, оформить коммиты (научиться git-у), сделать rebase поверх master, сделать PRы.
  • Не спеша разобраться с каждым PR по порядку. (Например, я буду против оптимизации кода Стрибога, если она будет не понятна и не будет давать прироста производительности как ваша предыдущая оптимизация.)

@vt-alt Во-первых, тот PR #190 был первым в серии изменений функции streebog и затрагивал исключительно только один аспект — устранение излишнего использования промежуточных буферов памяти при обработке входных данных функции streebog.
Сложно было от этого заметить сколько-нибудь существенного изменения в синтетическом тесте, проводимом в обычных (не под высокой нагрузкой на шину данных и процессорный кеш ). В большей степени на результаты могло повлиять то, как компилятор обработал эти изменения и создал результирующй код. Если при этом сравнительное тестирование показало значимое падение скорости, нужно дополнительное внимание к параметрам компиляции и используемому компилятору.
Во всяком случае мне не удалось выявить такого падения. Разброс показаний скорости выполнения алгоритма до и после , в бОльшей степени вызван случайными факторами .
Вот данные полученные в серии прогонов , сравниваются черным — базовая реализация, синим — с применением патча.
https://user-images.githubusercontent.com/27359066/71379638-147da480-25dd-11ea-8022-8f376b85002d.png.

С какой целью были внесены эти изменения.
Изменение нужно было для следующего шага — использование возможностей CPU архитектуры x86 эффективно читать 128бит невыровненные данные + задействование SSE2 оптимизированных инструкций для выполнения LPS преобразования алгоритма streebog. Это раскрывает потенциал современных CPU построенных на этой архитектуре и дает заметный прирост в скорости. Для SIMD оптимизаций я использовал практически без изменения уже имеющийся в кодовой базе, но по какой-то причине выключенный из сборки, gosthash2012_sse2.h — реализацию Дегтярева.
Изменения в PR сделаны с учетом того ,чтобы избежать негативного влияния на производительность для прочих архитектур, не реализующих SSE и неспособных читать невыровненные данные. Но этот момент требует отдельной проверки. Я не имею возможности провести качественный тест на широком круге архитектур. (отмечу, что travis CI проходит все тесты для x86_64/ppc/aarch64 для linux/osx собранные gcc/clang , но опираться на скоростные покатели при выполнении в среде travis нельзя)

Привожу тесты для x86_64, полученные по итогам применения тех изменений, которые касаются streebog.

Intel Core i5-4210U CPU @ 1.70GHz
Linux x86_64 GNU/Linux

compare streebog digest calculation

github.com/gost-engine/engine @09615031fffa93d7b42af7ad1029d963445c7c74

GOST-R 34.11-2012(512). block size / digest speed, MBps
 /size          32        64       256      1024      8192      9732     65536
------------------------------------------------------------------------------
       1      6.83     11.18     26.80     40.96     46.02     43.10     41.69
       2      5.45     11.47     27.70     41.38     48.18     48.54     47.43
       3      7.19     11.55     27.50     41.05     48.20     48.45     47.10
       4      7.48     11.51     28.26     41.35     47.46     49.62     48.27
       5      7.52     11.69     27.70     42.30     48.75     49.36     50.12
------------------------------------------------------------------------------

github.com/ddulesov/engine @e8b84331c31fb38f2eed437f4675633b846e0f3e

 GOST-R 34.11-2012(512). block size / digest speed, MBps
 /size          32        64       256      1024      8192      9732     65536
------------------------------------------------------------------------------
       1     13.58     22.38     55.46     87.51    100.05    103.75     98.60
       2     12.70     20.12     53.74     86.84    102.69    103.32    105.44
       3     13.70     21.90     55.48     87.48    102.09     91.67    104.02
       4     13.64     21.16     49.96     86.11    101.11    103.12     99.33
       5     13.38     21.64     54.34     84.41    102.17     90.81     99.52
------------------------------------------------------------------------------

в обоих случаях сборка производилась так

#cmake -DOPENSSL_ROOT_DIR=${PREFIX} -DOPENSSL_LIBRARIES=${PREFIX}/lib -DOPENSSL_ENGINES_DIR=${PREFIX}/lib/engines-1.1 .. && make

gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

на базе
OpenSSL 1.1.1e github.com/openssl/openssl/tree/OpenSSL_1_1_1-stable @c8943eb04ae41506ec8a1869103e2e1dec6bfcd8

platform: linux-x86_64
options: bn(64,64) rc4(16x,int) des(int) idea(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -m64 -Wa,—noexecstack -Wall -O3 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG

Это показывает, что для архитектуры x86_64 задействование SIMD дает практически 100% увеличение скорости работы* функции streebog-hash.

И второе. Все это синтетические тесты, которые весьма далеки от реального использования алгоритма.
Тестовые данные кратны 64 байт, то есть размеру блока данных алгоритма streebog. В этом случае при выполнении исключается ветка алгоритма, выполняющая паддинг данных.
В реальных условиях данные могут быть любой длины.
Давайте сравним результаты прикладного теста. В наборе утилит есть gost12sum, которая выполняет вычисление и сравнение хеш-сумм файлов.
В форкнутой версии я добавил утилиту gost1sum с той же функциональностью. При выполении проверки хеш-сумм этими утилитами основное время затрачивается алгоритмом вычисления хеша.
Для тестирования можно использовать любой набор файлов общим объемом от 1Гб. В этом случае уменьшается влияние случайных факторов. Для уменьшения влияния кеширования данных в ядре Linux тесты лучше повторить несколько раз.

Создаем check-file

#find /path_to_files(>1Gb)  -type f -exec ./bin/gost12sum -v {} \; > .check

сравниваем время проверки хеш сумм

из upstream github.com/gost-engine/engine

#time ./bin/gost12sum -c .check

из github.com/ddulesov/engine

#time ./bin/gost1sum -c .check

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

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

Вариант 1: gost.dll — open source библиотека, которая раньше поставлялась вместе с OpenSSL, но начиная с версии OpenSSL 1.1, она была исключена из его состава, и оформилась в виде отдельного продукта https://github.com/gost-engine/engine .

Поддержка алгоритмов ГОСТ 2001 имеется во всех версиях библиотеки gost.dll. Однако поддержка алгоритмов ГОСТ 2012 реализована только в версиях, совместимых с OpenSSL >= 1.1.0.

Библиотека gost.dll должна использоваться только с соответствующей ей версией OpenSSL:

  • для OpenSSL < 1.1.0: берется из поставки самого OpenSSL, НЕподдерживает ГОСТ 2012
  • для OpenSSL >= 1.1.0: собирается самостоятельно из исходников ( https://github.com/gost-engine/engine ),  поддерживает ГОСТ 2012

В релизах сервиса до сентября 2020 включительно, использовались библиотеки OpenSSL 1.0.2. Поэтому возможно использовать библиотеку gost.dll из самого интялятора OpenSSL, либо можно скачать соответствующую библиотеку с нашего сайта:

  • Win32: https://techmill.ru/paruspub/parus8.5.6.1-2020.09/gost/gost.dll
  • Win64: https://techmill.ru/paruspub/parus8.5.6.1-2020.09/gost/win64/gost.dll

В штатной поставке текущего сервиса поставляются библиотеки OpenSSL версии 1.1.1. Поэтому необходимо самостоятельная сборка библиотеки gost.dll, либо можно воспользоваться версией собранной нами:

  • Win32: https://techmill.ru/paruspub/current/gost/gost.dll
  • Win64: https://techmill.ru/paruspub/current/gost/win64/gost.dll

Важно!

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

Развертывание :

  1. Расположить библиотеку gost.dll нужной разрядности в каталог установки текущего сервиса, рядом с исполняемыми файлами, которые будут ее использовать. В случае использования Win64 разрядности сервиса — это подкаталог WIN64.
  2. Создать файл конфигурации OpenSSL:

    01openssl_conf = openssl_def
    02
    03[openssl_def]
    04engines = engine_section
    05
    06[engine_section]
    07gost = gost_section
    08
    09[gost_section]
    10engine_id = gost
    11dynamic_path = ./gost.dll
    12default_algorithms = ALL
    13CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
        

    В указанном примере файла конфигурации предполагается, что библиотека поддержки алгоритмов ГОСТ находится рядом с исполняемыми файлами. Но файл конфигурации может быть расположен в ином месте. В таком случае необходимо указать полный, а не относительный путь к библиотеке. Кстати, в качестве разделителя каталогов пути необходимо использовать прямой слэш «/» как в Unix, а не обратный, как в Windows, либо экранировать обратные слэши еще одним обратным слэшем — «\\».

    В случае использования существующего файла конфигурации, например поставляемого с самим OpenSSL, необходимо 1-ю строчку (openssl_conf = openssl_def) вставить в начало этого файла, а остальные строки в самый конец файла.

    Указанный файл конфигурации является примером, и может быть изменен пользователем в зависимости от требуемых настроек.

    Кстати

    Подобным образом возможно подключить любые другие расширения (engine) для OpenSSL.

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

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

    engine:id расширения:путь к закрытому ключу согласно документации криптопровайдера
            

    Например:

    engine:gostengy:techmill.ru
            
  3. Установить системную переменную окружения ОС с именем OPENSSL_CONF и значением указывающим полный путь к файлу конфигурации OpenSSL.

    Кстати

    В случае настройки клиента удаленного доступа для приложения Win32, это удобно настроить (как подключение файл конфигурации OpenSSL, так и установка переменной окружения OPENSSL_CONF) в процессе конфигурирования на странице Дополнительные модули и переменые окружения в составе клиента удаленного доступа.
  4. В файле конфигурации текущего сервиса MillAppServer.conf, который находится рядом с исполняемым файлом в зависимости от используемой разрядности, в элементе /config/object[@class=»{91D7A767-7222-4463-BC7F-AD40589E3426}»] найти и изменить (или в случае его отсутствия, добавить) узел <param name=»CipherList» value=»GOST2012-GOST8912-GOST8912 GOST2001-GOST89-GOST89 GOST94-GOST89-GOST89″/> для поддержки всех версий ГОСТ — 2012, 2001 и 94, либо <param name=»CipherList» value=»GOST2012-GOST8912-GOST8912″/> для поддержки только версии ГОСТ 2012.

В случае проблем с использованием настроенного и запущенного сервиса, для проверки его работоспособности рекомендуется использовать утилиту openssl в режиме клиента TLS, с помощью команды openssl s_client -connect 127.0.0.1:443. В случае успешного соединения с сервером в выводе консоли будет указана вся информация об установленном соединении, такая как сертификат, версия протокола TLS, используемый шифр и многое другое. Перед использованием OpenSSL утилиты необходимо аналогично обеспечить настройку файла конфигурации OpenSSL, как указано в пункте 2 и установить системную переменную окружения ОС с именем OPENSSL_CONF, как указано в пункте 3.

Окружение

  • Версия РЕД ОС: 7.3
  • Конфигурация: Рабочая станция
  • Версия ПО: 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

Дата последнего изменения: 16.06.2023

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

OpenSSL GOST представляет собой криптографический движок, разработанный для операционной системы Windows, который поддерживает использование алгоритмов шифрования ГОСТ. Этот движок позволяет использовать криптографические функции ГОСТ, такие как шифрование, генерация и проверка электронной подписи, а также работы с сертификатами.

Основные возможности OpenSSL GOST включают поддержку алгоритмов шифрования, используемых в ГОСТ, включая Кузнечик, Магма и другие. Это позволяет обеспечить защищенное хранение и передачу информации, используя криптографические механизмы, основанные на отечественных стандартах и алгоритмах.

OpenSSL GOST предоставляет универсальный интерфейс для работы с криптографическими функциями ГОСТ и интегрируется с различными приложениями, такими как веб-браузеры, почтовые клиенты, программы для шифрования файлов и другими. Это делает его удобным и эффективным инструментом для обеспечения безопасности в среде Windows.

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

Содержание

  1. Поддержка криптографического движка OpenSSL GOST в Windows
  2. Преимущества и возможности криптографического движка OpenSSL GOST
  3. Установка и настройка криптографического движка OpenSSL GOST для Windows

Поддержка криптографического движка OpenSSL GOST в Windows

Для работы криптографического движка OpenSSL GOST в Windows необходимо выполнить следующие шаги:

  1. Установить OpenSSL на компьютер с операционной системой Windows.
  2. Скачать и установить криптопровайдер Крипто Про CSP.
  3. Настроить OpenSSL для работы с криптопровайдером Крипто Про CSP.
  4. Скомпилировать криптографический движок OpenSSL GOST.
  5. Настроить OpenSSL для использования криптографического движка OpenSSL GOST.

После выполнения этих шагов можно начать использовать криптографический движок OpenSSL GOST для выполнения различных операций, таких как генерация ключей, шифрование и дешифрование данных, подписывание и проверка подписей.

Криптографический движок OpenSSL GOST обеспечивает высокую степень безопасности, используя стандартные алгоритмы шифрования и хэширования, определенные в ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012. Эти алгоритмы обеспечивают надежную защиту данных и широко применяются в различных областях, таких как интернет-банкинг, электронная коммерция, электронный документооборот и многое другое.

Поддержка криптографического движка OpenSSL GOST в Windows позволяет использовать современные алгоритмы шифрования и хэширования для защиты ценной информации. Это дает возможность обеспечить конфиденциальность и целостность данных, а также проверить подлинность сообщений и данных.

Преимущества и возможности криптографического движка OpenSSL GOST

Преимущества использования OpenSSL GOST включают:

  1. Поддержка стандартов ГОСТ — OpenSSL GOST предоставляет реализацию алгоритмов шифрования, хэширования и цифровой подписи, определенных российскими стандартами ГОСТ. Это позволяет использовать эти алгоритмы для защиты информации, соответствующей российским требованиям и нормам безопасности.
  2. Совместимость с OpenSSL — OpenSSL GOST интегрируется в существующий код и приложения, использующие OpenSSL. Это позволяет легко адаптировать существующие решения для работы с алгоритмами ГОСТ без необходимости переписывания значительного объема кода.
  3. Поддержка различных операционных систем — OpenSSL GOST доступен для использования на различных операционных системах, включая Windows. Это делает его удобным выбором для разработчиков и администраторов, работающих с различными платформами.
  4. Надежность и безопасность — OpenSSL GOST прошел множество проверок на безопасность и широко используется в различных сферах, включая финансовые и банковские учреждения. Он предоставляет высокий уровень безопасности и надежности для защиты конфиденциальной информации.

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

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

Установка и настройка криптографического движка OpenSSL GOST для Windows

Шаг 1: Скачайте и установите бинарные файлы OpenSSL для Windows с официального сайта OpenSSL. Выберите подходящую версию для вашей операционной системы.

Шаг 2: Распакуйте скачанный архив с бинарными файлами OpenSSL в удобную для вас директорию на компьютере.

Шаг 3: Скачайте криптографический движок OpenSSL GOST для Windows с официального репозитория на GitHub.

Шаг 4: Распакуйте скачанный архив с криптографическим движком OpenSSL GOST в ту же директорию, где распакованы бинарные файлы OpenSSL.

Шаг 5: Откройте командную строку и перейдите в директорию, где находятся распакованные бинарные файлы OpenSSL.

Шаг 6: Выполните следующую команду в командной строке, чтобы сконфигурировать бинарные файлы OpenSSL с криптографическим движком OpenSSL GOST:

config -Tm32 -DOPENSSL_NO_HEARTBEATS -L. -d enable-gost -Iopenssl -Ie:/path/to/openssl-gost -Ie:/path/to/openssl-gost/crypt -Ie:/path/to/openssl-gost/x509

Замените пути e:/path/to/openssl-gost на реальные пути, где вы распаковали архив с криптографическим движком OpenSSL GOST.

Шаг 7: Выполните следующую команду в командной строке, чтобы скомпилировать и установить бинарные файлы OpenSSL с криптографическим движком OpenSSL GOST:

ms\do_nasm nmake -f ms
t.mak
nmake -f ms
t.mak test
nmake -f ms
t.mak install

Шаг 8: После успешной компиляции и установки бинарных файлов, вы можете использовать криптографический движок OpenSSL GOST в своих проектах на Windows.

Теперь у вас установлен и настроен криптографический движок OpenSSL GOST для Windows. Вы можете использовать ГОСТ алгоритмы в OpenSSL на платформе Windows.

Время на прочтение
11 мин

Количество просмотров 36K

Встала перед нами в полный рост задача наладить взаимодействие с ГИС ЖКХ. Согласно документации, предполагается использование небезызвестного отечественного ПО для шифрования туннеля и формирования ЭЦП по ГОСТу, но это не наш метод. Вооружившись гуглом и консолью, я и slavam реализовали необходимый функционал подручными средствами.
Всё необходимое ПО есть как на Linux, так и на Windows платформах, потому методику можно назвать мультиплатформенной.

  1. Подготовка
  2. Криптотуннель по ГОСТу
  3. Формирование XMLDSig
  4. Ссылки

Подготовка

Взаимодействие состоит из следующих частей:

  • Установка по ГОСТу шифрованного туннеля до серверов ГИС ЖКХ.
  • Формирование и отправка подписанного XML запроса.
  • Получение и проверка ответа.

Для работы используется сервер CentOS 6, Python 2.7.11, OpenSSL + GOST engine, stunnel. Краткая инструкция установки openssl с поддержкой ГОСТ

для ленивых:

# wget https://www.openssl.org/source/openssl-1.0.2g.tar.gz
# tar -xvf openssl-1.0.2g.tar.gz
# cd openssl-1.0.2g/
# yum groupinstall "Development Tools"
# yum install zlib zlib-devel
# ./config shared zlib enable-rfc3779
# make && make install
# echo "/usr/local/ssl/lib/" > /etc/ld.so.conf.d/openssl.conf
# ldconfig
# /usr/local/ssl/bin/openssl ciphers | tr ":" "\n" | grep -i gost
GOST2001-GOST89-GOST89
GOST94-GOST89-GOST89

# cat /usr/local/ssl/openssl.cnf
…………
openssl_conf = openssl_def

[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
engine_id = gost
default_algorithms = ALL
…………

Думаю, ничего сложного быть не должно и всё уже сотни раз описано. А в более свежих дистрибутивах модуль gost есть из коробки.

OpenSSL используется двояко: с ним собран stunnel, что-бы работал по ГОСТу; и утилита openssl вызывается из кода python-а для формирования и проверки подписей. Вызов openssl обусловлен тем, что не удалось из кода python-на задавать используемый крипто-модуль. Всё необходимое ПО есть как на Linux, так и на Windows платформах, потому методику можно назвать мультиплатформенной.

Для python-а сервера CentOS 6 нужно будет обновить библиотеку lxml, а для этого поставить несколько дополнительных пакетов:

# yum install libxml2 libxml2-devel libxslt libxslt-devel python-devel
# pip install lxml --upgrade

Так же нам потребуются файлы сертификата и закрытого ключа в формате PKCS12 (.pem). Получить их из eToken-а можно с помощью утилит вроде P12FromGostCSP или вручную. Если сделать это по каким-либо причинам не получается, то есть вариант работы с ключом «Рутокен ЭЦП» напрямую. На сайте есть подробные инструкции, как обучить этому OpenSSL и stunnel. Таким образом, задача сводится к предыдущей. У меня под рукой такого ключа не оказалось, потому проверить не удалось.

Криптотуннель по ГОСТу

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

# wget https://www.stunnel.org/downloads/stunnel-5.31.tar.gz
# tar -xvf stunnel-5.31.tar.gz
# cd stunnel-5.31

Правим файл src/options.c и в конце функции «NOEXPORT char *engine_init(void)» добавляем вызов SSL_library_init();.

Получится как-то так:

NOEXPORT char *engine_init(void) {
    if(engine_initialized) /* either first or already initialized */
        return NULL; /* OK */
    s_log(LOG_DEBUG, "Initializing engine #%d (%s)",
        current_engine+1, ENGINE_get_id(engines[current_engine]));
    if(!ENGINE_init(engines[current_engine])) {
        if(ERR_peek_last_error()) /* really an error */
            sslerror("ENGINE_init");
        else
            s_log(LOG_ERR, "Engine #%d (%s) not initialized",
                current_engine+1, ENGINE_get_id(engines[current_engine]));
        return "Engine initialization failed";
    }
#if 0
    /* it is a bad idea to set the engine as default for all sections */
    /* the "engine=auto" or "engineDefault" options should be used instead */
    if(!ENGINE_set_default(engines[current_engine], ENGINE_METHOD_ALL)) {
        sslerror("ENGINE_set_default");
        return "Selecting default engine failed";
    }
#endif
    s_log(LOG_INFO, "Engine #%d (%s) initialized",
        current_engine+1, ENGINE_get_id(engines[current_engine]));
    SSL_library_init();
    engine_initialized=1;
    return NULL; /* OK */
}

Решение было найдено тут.
Собираем с подключением ранее собранного OpenSSL:

# ./configure --with-ssl=/usr/local/ssl  --disable-libwrap
# make && make install

Файл конфигурации /etc/stunnel.conf:

client=yes
# сертификат ГИС ЖКХ (тестовый).
CAFile=/etc/crypto/CA-SIT.pem
engine=gost
sslVersion=TLSv1
engineDefault = ALL

output=/var/log/stunnel.log
DEBUG=4

# извлечённые с eToken-а.
cert=/etc/crypto/public.pem
key=/etc/crypto/private.key

[pseudo-https]
# адрес и порт сервера, который будет принимать запросы.
accept = 10.1.5.133:8080
# адрес сервера ГИС ЖКХ, куда прокладываем туннель (тестовый).
connect = 54.76.42.99:60045
ciphers = GOST2001-GOST89-GOST89

Файлы сертификатов кладём в директорию /etc/crypto/. В общем случае, stunnel может работать под любым пользователем, но у нас пусть будет root.

Простейший init.d скрипт управления службой:

#! /bin/bash
#
# stunnel          Start/Stop Stunnel
#
# chkconfig: 2345 90 60
# description: launches Stunnel
# processname: stunnel
# config: /etc/stunnel.conf

# Source function library.
. /etc/init.d/functions

# See how we were called.

prog="Stunnel CryptoTunnel"
RNG=PROGRAM
export RNG

start() {
    echo -n $"Starting $prog: "
    /usr/local/bin/stunnel  /etc/stunnel.conf
    RETVAL=$?
    [ $RETVAL -eq 0 ] && success
    [ $RETVAL -ne 0 ] && failure
    echo
    return $RETVAL
}

stop() {
    echo -n $"Stopping $prog: "
    /usr/bin/killall /usr/local/bin/stunnel >/dev/null 2>&1
    RETVAL=$?
        [ $RETVAL -eq 0 ] && success
        [ $RETVAL -ne 0 ] && failure
        echo
        return $RETVAL
}

restart() {
    stop
    start
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    restart
    ;;
  *)
    echo $"Usage: $0 {start|stop|status|restart}"
    exit 1
esac

Можно запускать и проверять, например,

запросом на адрес сервера:

# curl http://10.1.5.133:8080/ext-bus-nsi-service/services/Nsi?wsdl
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi-service/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:nsi-common="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi-common/" xmlns:nsi="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi/" xmlns:ns="http://www.w3.org/2000/09/xmldsig#" xmlns:base="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/" targetNamespace="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi-service/">
  <wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi-service/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:nsi-common="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi-common/" xmlns:nsi="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi/" xmlns:ns="http://www.w3.org/2000/09/xmldsig#" xmlns:base="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/">

  <xs:import namespace="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/" schemaLocation="http://54.76.42.99:60046//ext-bus-nsi-service/services/Nsi?xsd=hcs-basetypes-8.7.0.7.xsd"/>

  <xs:import namespace="http://dom.gosuslugi.ru/schema/integration/8.7.0.7/nsi/" schemaLocation="http://54.76.42.99:60046//ext-bus-nsi-service/services/Nsi?xsd=hcs-nsi-types-8.7.0.7.xsd"/>

</xs:schema>
………

Если вывод совсем не похож, то внимательно смотрим в лог файл /var/log/stunnel.log.

Формирование XMLDSig

Когда туннель до сервера ГИС ЖКХ настроен и работает, можно слать туда всякие запросы и получать нужные ответы. Запрос отправляется в виде XMLDSig, в котором содержится сам запрос, хеш этого запроса, хеш сертификата, сам сертификат, подпись хеша запроса с хешем сертификата и куча полей, всё это описывающих. Самое сложное как раз было раскрутить всю цепочку и получить XML, который успешно проходит проверку со стороны ГИС ЖКХ. Все подписываемые блоки берутся в каноническом виде, а получаемые подписи и хеш-суммы кодируются в BASE64.

Алгоритм формирования XMLDSig можно реализовать используя любой удобный язык программирования. Мы использовали python 2.7.11, демонстрационный код прилагается. Как пример, буду так же приводить консольный аналог.

0. Из сертификата достаются серийный номер и данные о выпустившем, генерируются необходимые id и запоминается текущее время.
1. С помощью любого soap клиента (например, suds на Python) формируется SOAP-запрос к серверу ГИС ЖКХ.

Пример SOAP-запроса:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
        xmlns:ns0="http://dom.gosuslugi.ru/schema/integration/8.7.0.3/nsi/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<RequestHeader
        xmlns="http://dom.gosuslugi.ru/schema/integration/8.7.0.4/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Date>2016-04-11T14:28:28</Date>
<MessageGUID>29f93de1-25b6-21e5-24ae-2c6f65dfe2b2</MessageGUID>
<SenderID>4eb0a7d6-6317-45cf-8974-10e75cbb0cbc</SenderID>
</RequestHeader>
</SOAP-ENV:Header>
<ns1:Body>
<ns0:exportDataProviderNsiItemRequest Id="signed-element">
<ns0:RegistryNumber>51</ns0:RegistryNumber></ns0:exportDataProviderNsiItemRequest>
</ns1:Body>
</SOAP-ENV:Envelope>

Где SenderID — идентификатор управляющей компании, от лица которой делается запрос. MessageGUID — уникальный ID, генерируемый как пожелается. Тело <ns1:Body> — сам запрос с дополнительными полями. Id="signed-element" — ID запроса, который указываем, как хотим и на который ориентируемся, подписывая запрос.

2. Берётся содержимое тега <ns1:Body>(точнее часть с Id и без первого и последнего символа перевода строки), канонизируется алгоритмом C14N (exclusive=True), считается от неё хеш-сумма по ГОСТу и выводится в виде BASE64. Получаем digest1. Консольный аналог:

# cat in.xml ; echo
<ns0:exportDataProviderNsiItemRequest Id="signed-element">
<ns0:RegistryNumber>51</ns0:RegistryNumber></ns0:exportDataProviderNsiItemRequest>
# cat in.xml | openssl dgst -engine gost -md_gost94  -binary | base64

* openssl с поддержкой ГОСТ. Engine указан явно, но, настроив openssl.cnf, можно этого и не делать.

3. Берётся сертификат в x509, декодируется из BASE64, считается от него хеш-сумма и вывод кодируется в BASE64. Получаем digest2.

4. Используя полученные данные, формируется содержимое тега <xades:SignedProperties>(см. Шаблон), канонизируется алгоритмом C14N (exclusive=False) и от содержимого считается digest3 (BASE64).

5. Формируется блок <ds:SignedInfo>, канонизируется алгоритмом C14N (exclusive=False), подписывается и кодируется в BASE64. Получается значение блока <ds:SignatureValue>. Консольный аналог:

cat SignedInfo.xml | openssl dgst -sign private.key -engine gost -md_gost94 -binary | base64 

где SignedInfo.xml – уже канонизированный блок, без последнего перевода строки.

6. Все полученные значения вносятся в

Шаблон XML-документа формата XAdES-BES:

<ds:Signature Id="xmldsig-{signature_id}" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
<ds:Reference Id="xmldsig-{signature_id}-ref0" URI="#{signed_id}">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
<ds:DigestValue>{digest1}</ds:DigestValue>
</ds:Reference>
<ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-{signature_id}-signedprops">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
<ds:DigestValue>{digest3}</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="xmldsig-{signature_id}-sigvalue">
{signature_value}
</ds:SignatureValue>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
{x590_cert}
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object><xades:QualifyingProperties Target="#xmldsig-{signature_id}" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#"><xades:SignedProperties Id="xmldsig-{signature_id}-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>{signing_time}</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/><ds:DigestValue>{digest2}</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>{x509_issuer_name}</ds:X509IssuerName><ds:X509SerialNumber>{x509_sn}</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object>
</ds:Signature>

Этот шаблон удалось сформировать расковыряв и проанализировав комплекс, который рекомендует использовать ГИС ЖКХ. Сам он находится в свободном доступе, но для работы требует СКЗИ КриптоПро CSP и СКЗИ Trusted Java 2.0.

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

# cat SignedInfo.xml | openssl dgst -engine gost -md_gost94 -verify <(openssl x509 -engine gost -in public.pem -pubkey -noout) -signature signature.sig

где signature.sig – раскодированная из BASE64 подпись, а SignedInfo.xml проверяемый блок <ds:SignedInfo>...</ds:SignedInfo> целиком. Значения хеш-сумм просто сравниваются.

Демонстрационный код на python-е можно взять и использовать (на свой страх и риск) отсюда. Автор кода — Вячеслав (@slavam, RO). Подобный алгоритм можно реализовать средствами любого удобного языка, без необходимости покупки каких-либо дополнительных средств и компонентов. Вызов утилит OpenSSL из кода хоть и выглядит топорным, зато работает как на Linux так и на Windows платформе и позволяет отказаться от использования КриптоПро и дополнительных компонентов.
Система взаимодействия с ГИС ЖКХ у нас ещё на стадии создания, но получаемый XMLDSig проходит необходимые проверки.
Надеемся, эта статья облегчит кому-нибудь задачу по реализации подобного велосипеда.

UPD
В порядке взаимодействия с ГИС ЖКХ происходят изменения. С актуальными правилами можно ознакомится на сайте. Основные изменения:

  • Теперь для работы с системой необходимо зарегистрировать ИС.
  • Перед тем, как слать запросы, необходимо выполнить basic-авторизацию.
  • Для работы с тестовым стендом, также нужно подать заявку.

Так же появились вполне приличные программные примеры, которые (если постараться) можно подружить и с OpenSSL.

UPD2
Чтобы завести OpenSSL под windows с поддержкой ГОСТ нужно:
1. Поставить OpenSSL от сюда, он уже с поддержкой GOST, в папке lib есть соответствующая библиотека: gost.lib.

2. В файле конфигурации явно указать его использование:

openssl_conf = openssl_def

[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
engine_id = gost
dynamic_path = ./gost.dll
default_algorithms = ALL

Чтобы точно определить, от куда OpenSSL читает конфигурацию, можно выставить переменную окружения:

set OPENSSL_CONF=C:\OpenSSL-Win32\openssl.cnf

3. Проверить результат:

C:\OpenSSL-Win32\bin>openssl.exe ciphers -v | find /I "gost"
GOST2001-GOST89-GOST89  SSLv3 Kx=GOST     Au=GOST01 Enc=GOST89(256) Mac=GOST89
GOST94-GOST89-GOST89    SSLv3 Kx=GOST     Au=GOST94 Enc=GOST89(256) Mac=GOST89

Спасибо за внимание.

Cсылки

  • Регламент и форматы информационного взаимодействия внешних информационных систем с ГИС ЖКХ (текущие форматы v.8.7.0.7)
  • Good-Samaritan/signature-demo
  • HOWTO use Stunnel with GOST
  • «Почему всем можно, а мне нельзя?» или реверсим API и получаем данные с eToken
  • XMLDSig: формат подписи XML

  • Openssl for windows x64 download
  • Openserver как установить на windows 10
  • Openssh сервер для windows 10
  • Openserver cannot create file c windows system32 drivers etc hosts
  • Openssh server для windows скачать