Настройка КриптоПро Stunnel для взаимодействия с TSP-службами ЦБ РФ
Опубликовано Николаем Диковым on 2023-11-13 19:18
Сертификаты
Изображение | Описание | Статус |
---|---|---|
Создание запроса на сертификат для Цифрового рубля | Опубликовано Захаром Тихоновым on 2023-10-19 12:08 |
Для создания запроса на сертификат на КриптоПро УЦ 2.0 (варианты исполнения 15, 16) требуется подготовить конфигурационный файл (extensions.json). Файл имеет формат JSON.
Для создания запроса используется командная строка управления инфраструктурой УЦ (pkica) и указывается путь к созданному конфигурационному файлу.
Пример:
pkica ca new-cert-req --subject CN=CA,O=BankTest,L=CBDC,S=77,C=RU --container-name ca --is-ca --key-index 0 --path-length 0 --subject-sign-tool СКЗИ КриптоПро CSP 5.0 R2 КС2 (исполнение 2-Base) --extensions-file /path/extensions.json --out-file /path/ca.req
Внимание: Сертификаты необходимо выпускать строго на технологическом УЦ. Использовать 1 набор TLS сертификатов для аккредитованного и технологического УЦ нельзя!!! Также необходимо разделять DN для клиентских сертификатов, используемых в NATS TLS в технологическом УЦ и аккредитованном!
Предполагается, что перед выпуском данных сертификатов, уже настроен технологический УЦ, в конфигурации c NATS без TLS.
Список сертификатов для NATS TLS
- Серверный сертификат NATS, выпускается по шаблону TLS сервер и должен содержать в CN или в SAN DNS имя машины/IP адрес.
Создание запроса на сертификат рекомендуется производить на машине, на которой непосредственно располагается соответствующий компонент УЦ, чтобы избежать в дальнейшем процедуры переноса ЗК.
Создание запроса и выпуск сертификатов могут быть выполнены как через веб-интерфейс, так и с помощью утилиты pkica.
Важно: для технологического УЦ, чтобы разрешить выпуск не только квалифицированных сертификатов, правим настройки ЦС. Надо настройке QualifiedCertMode установить значение AttrFormat или None, Затем перезапустить службу ЦС.
Процедура подробно описана в пункте 1.2.6. Руководства по эксплуатации.
Пример команд для выпуска сертификата, указанного в пункте 1 списка сертификатов с использованием pkica:
example command
Если Вы хотите добавить несколько DNS имен в SAN, то запрос создания должен выглядеть так:
example command
Устанавливаем сертификат с привязкой к ЗК (обязательно под тем же пользователем, под которым создавали запрос).
Пример выпуска сертификата, указанного в пункте 1 списка сертификатов с использованием веб-интерфейса:
example command
Создаем пользователя и выпускаем ему сертификат, по шаблону Cервер TLS, не забывая указать верные SAN.
Затем создаем pfx и устанавливаем его на УЦ под тем пользователем, под которым запускается демон NATS.
Важно: при установке pfx не задаем пароль.
Для сертификатов, описанных в пунктах 2-6 списка сертификатов, отличаться будет только процедура создания запроса, мы будем использовать другой шаблон и для каждого пункта указываем свой уникальный DN. Процесс выпуска и установки не будет отличаться.
Пример команд для создания запроса на сертификат, описанных в пунктах 2-6 списка сертификатов:
## Пример выпуска сертификатов
## Создание пользователя и сертификата
Для начала необходимо создать пользователя и выдать ему сертификат с использованием шаблона Клиент TLS.
## Установка сертификата на УЦ
После этого создаем файл формата PFX и устанавливаем его на УЦ под пользователем, под которым запускается демон соответствующего сервиса.
## Редактирование файла nats.conf
Отредактируем файл nats.conf, указав пути к файлам серверного и клиентского сертификатов.
### Для серверного сертификата
Путь указывается в разделе:
серверныйсертификат NATS
### Для клиентского сертификата
Путь указывается в разделе:
NATS Streaming Configuration
клиентский сертификат NATS Streaming для подключения к сервису NATS
Не забудьте добавить корректный порт и DNS имя в раздел listen.
## Обновление конфигураций сервисов
В файлах appsettings.json соответствующих сервисов в разделах NATS/STAN укажите отпечаток tls сертификата и установите значение параметра Secure в true.
## Запуск NATS с TLS
После внесения изменений в конфигурационные файлы, остановите демоны сервисов УЦ и произведите пробный запуск NATS с TLS через bash.
Пример запуска:
/opt/cpca_tls/nats-streaming/nats-streaming-server -sc /opt/cpca_tls/nats-streaming/nats.conf
Убедитесь, что NATS успешно запущен и завершите процесс.
## Обновление демонов
Если для NATS без TLS ранее был создан демон, отредактируйте его настройки, указав путь к новому файлу конфигурации. Также можно создать новый демон, отключив автозагрузку старого.
## Завершение настройки
Запустите демоны сервисов УЦ и убедитесь, что соединение успешно установлено.
После включения TLS для NATS, через pkica нельзя будет выпустить сертификаты с неподписанными запросами. Подписать запрос необходимо сертификатом оператора.
## Проблемы с CRL
Если по какой-то причине не удается выпустить CRL в конфигурации с NATS TLS, необходимо выполнить следующие действия:
1. Остановить демоны сервисов УЦ и NATS.
2. Запустить Nats вручную с конфигурацией без TLS.
3. После успешного запуска NATS, редактировать файл appsettings.json в CryptoPro.Ca.Service, убрав требование Secure.
4. Затем исправить appsettings.json в pkica аналогичным образом.
5. Запустить CryptoPro.Ca.Service и вручную выпустить CRL, указав директорию публикации.
6. Распространить CRL на все компоненты УЦ.
Не забудьте остановить CryptoPro.Ca.Service и NATS после успешного выпуска CRL, и активировать требование Secure в конфигурационных файлах appsettings.json.
## Последовательно запускаем Nats c TLS и остальные демоны УЦ
Привет, Хабр! Меня зовут Вадим, я Java-разработчик SimbirSoft. В этой статье я расскажу, как на одном из проектов мы реализовали возможность валидации электронной подписи с помощью КриптоПро JCP.
Этот фреймворк оказался хорошей альтернативой КриптоПро SVS после того, как последний попал под санкции Microsoft. Впоследствии на других подобных проектах я убедился в том, что решение рабочее и наиболее подходящее под бизнес-цели заказчиков. Прежде всего это банки, нанимающие организации и другие юрлица, где ведется электронный документооборот.
## Кадр из фильма Код Да Винчи
Наш клиент занимался переоборудованием автомобилей на газовое топливо. Для работы со своими заказчиками ему приходилось вызывать курьеров к каждому, чтобы подписать тот или иной документ. Это было крайне неудобно и затратно. Поэтому он обратился к нам, чтобы реализовать задачу валидации электронной подписи в короткий срок. Вместе с командой из двух разработчиков и одного тимлида нам удалось сделать это за один месяц.
## Решение
Чтобы решить задачу, мы провели исследование возможных вариантов валидации подписи. Одним из подходящих вариантов стал сервис КриптоПро SVS. Это обертка над КриптоПро CSP, которая предоставляет веб-сервис REST и SOAP для проверки подписи, а также проверяет валидность и квалифицированность сертификата.
Но при его развертывании в облачной среде Yandex Cloud мы столкнулись с проблемой. В период разработки нашей системы в 2022 году Yandex Cloud перестал поддерживать виртуальные машины Windows в связи с санкциями от компании Microsoft. А сервис SVS подразумевал развертывание в данной операционной системе.
Перенос системы в другой облачный сервис был невозможен, так как вся инфраструктура уже была настроена и успешно работала, переезд занял бы много времени и денег заказчика, а эти ресурсы мы стараемся беречь. Поэтому было принято решение создать свой сервис для валидации detached подписей на основе библиотеки КриптоПро JCP. Она оказалась более низкоуровневой, но доступной для реализации.
## О решении
КриптоПро JCP — средство криптографической защиты информации, реализующее российские криптографические стандарты. Разработано в соответствии со спецификацией JCA (Java Cryptography Architecture).
### Симметричное шифрование
Существует два основных вида шифрования — симметричное и ассиметричное. Мы остановимся на ассиметричном, так как именно оно используется в электронных подписях. Рассмотрим, как работает классический вид ассиметричного шифрования.
В данном виде шифрования используется два ключа:
1. Ключ шифрования (открытый ключ)
2. Ключ дешифрования (закрытый ключ)
Допустим, у нас есть два собеседника — Петя и Катя. Они работают на одном проекте, и естественно, на них распространяется NDA, который ни в коем случае нельзя нарушать. Поэтому Петя решает передать Кате код проекта в интернете с помощью ассиметричного шифрования.
```markdown
## Важно отметить
При такой схеме передачи нам не нужны защищенные каналы связи, так как перехват любых данных не имеет смысла. Восстановить исходную информацию возможно только при помощи закрытого ключа, который есть только у Кати.
## Ссиметричное шифрование в электронной подписи
Тут-то мы и подходим к валидации подписей. Как же это работает, и почему любой человек может проверить ее законность и корректность?
## Алидация подписи
Подписи бывают двух видов — отсоединенная, или detached, и присоединенная, или attached. Главное отличие этих подписей заключается в том, что при создании присоединенной подписи формируется один файл, который содержит и саму подпись, и документ. А при создании отсоединенной подписи формируется отдельный файл с расширением .sign, который содержит detached-подпись.
Для валидации обоих типов подписи используется одна логика. Сертификат электронной подписи пользователя связан с сертификатом удостоверяющего центра, который выдал ему эту подпись. Сертификат удостоверяющего центра связан с корневым сертификатом. Все сертификаты удостоверяющих центров и корневых сертификатов находятся в открытом доступе на портале УФО. По сути, для валидации подписи мы проходим по цепочке сертификатов, и если все они являются доверенными, то подпись является валидной.
## Еализация валидации на Kotlin c использованием JCP
Для Java есть стандартное хранилище доверенных CA-сертификатов (cacerts), которое используется для Java-приложений и является составной частью среды выполнения приложения — JRE (Java Runtime Environment). Оно располагается в директории jre/lib/security/cacerts. Нужно установить все корневые сертификаты с помощью команды:
```bash
keytool -importcert -cacerts -storepass changeit -file путь_до_сертификата.cer -alias название_сертификата_в_хранилище
Alias для сертификата можно придумывать любой!
Валидация detached подписи на Kotlin
Detaсhed-подпись является отдельным файлом с расширением .sign. Для валидации нам понадобится исходный файл, который подписывался.
Проперти, которые мы устанавливаем, указывают на то, что отозванные сертификаты будут искаться в интернете (участок кода взят из документации JCP).
Получение информации об электронной подписи
Помимо простой проверки электронной подписи с помощью JCP, мы можем получить массу информации о ней. Например, ФИО владельца, ИНН, ОГРН (если это юрлицо), номер сертификата и многое другое. Все это хранится в объекте cadesSignature
, который мы создали для валидации. Мы использовали эти данные для создания штампов в подписанных документах.
С помощью данного кода мы можем получить сертификат и извлечь нужные данные:
## Код выделен только для примера, не является рабочим кодом
certificate = cadesSignature.getCertificate()
name = certificate.getSubjectDN().getName()
inn = certificate.getIssuerDN().getName()
Остальные данные нам удалось получить слегка изощренным способом из-за того, что в классе X509CertImpl ИНН, ОГРН и ФИО не выделены в отдельные переменные. Все эти данные хранятся в поле subjectX500PrincipalInternal нашего объекта cert, поэтому мы преобразовали его в строку и применили к ней ряд регулярных выражений.
Далее мы просто применили эти регулярные выражения к нашему subject и получили все необходимые данные для штампа электронной подписи.
### Роблема получения информации из тестового сертификата
В ходе тестирования нашего решения мы использовали как реальные электронные подписи, так и тестовые сертификаты, которые можно легко выпустить на сайте Тестового удостоверяющего центра ООО "КРИПТО-ПРО". На реальных подписях все отрабатывало отлично, и мы получали всю необходимую информацию, но с тестовыми возникла проблема.
Дело в том, что при выпуске тестового сертификата электронной подписи в поле subjectX500PrincipalInternal хранится не так много информации, иногда оно может содержать всего одно значение. Вот реальный пример:
Поэтому для удобства тестирования мы создали интерфейс CertInfoProvider с методом получение информации, описанным выше. И создали две его имплементации CertInfoProviderProd, CertInfoProviderDev.
Таким образом, просто переключая параметр в конфиг мапе нашего сервиса мы могли очень гибко и быстро в случае необходимости включить, либо выключить валидацию тестовых сертификатов.
## Результат
В ходе работы нам удалось прежде всего сберечь денежный и временной ресурс заказчика.
Спасибо за внимание!
Больше авторских материалов для backend-разработчиков от моих коллег читайте в соцсетях SimbirSoft – ВКонтакте и Telegram.