Криптопро не видит контейнер на Rutoken S

Криптопро не видит контейнер на Rutoken S Электронная цифровая подпись

Эта статья посвящена тому, как перестать использовать Крипто Про и перейти на Bouncy Castle в девелоперском/тестовом окружении. В начале статьи будет больше про СМЭВ и его клиент, в конце — больше про конвертирование ключей с готовой копипастой, чтобы можно было начать прямо сейчас.

Картинка для привлечения внимания:

Криптопро не видит контейнер на Rutoken S

И сразу же ответ:

Криптопро не видит контейнер на Rutoken S

Оставлено
:
23 марта 2022 г. 20:13:10(UTC)

Такой вопрос, есть 2 организации с установленными криптопро как можно между ними организовать обмен файлами, предварительно зашифрованными через приложение cptools?

Я так понимаю Нам предварительно придется сначала создать а потом обменяться парами ключей? А как их создать? Эта платная услуга?

  • имя контейнера вместе со считывателем;
  • eos.req
    — имя файла, в котором следует сохранить запрос (вместо eos можно указать любое имя файла — *.req);
  • -certusage — опция, которая указывает назначение сертификата, представляемое в сертификате объектным идентификатором, присвоенным этой политике, — OID. Если в сертификате указано несколько политик, то это означает, что сертификат соответствует всем этим политикам списка:1.3.6.1.5.5.7.3.1 — аутентификация сервера;1.3.6.1.5.5.7.3.2 — аутентификация клиента;1.3.6.1.5.5.7.3.3 — подписывание кода;1.3.6.1.5.5.7.3.4 — защищенная электронная почта;1.3.6.1.5.5.7.3.8 — проставление штампов времени;1.3.6.1.4.1.311.10.5.1 — цифровые права;1.3.6.1.4.1.311.10.3.12 — подписывание документа.
  • 1.3.6.1.5.5.7.3.1 — аутентификация сервера;
  • 1.3.6.1.5.5.7.3.2 — аутентификация клиента;
  • 1.3.6.1.5.5.7.3.3 — подписывание кода;
  • 1.3.6.1.5.5.7.3.4 — защищенная электронная почта;
  • 1.3.6.1.5.5.7.3.8 — проставление штампов времени;
  • 1.3.6.1.4.1.311.10.5.1 — цифровые права;
  • 1.3.6.1.4.1.311.10.3.12 — подписывание документа.

Всем привет, с вами Искандер Рустамов, младший системный администратор Cloud4Y. Сегодня мы будем покорять развертывание центра сертификации (ЦС).

Из-за сложной геополитической обстановки резко усилился процесс импортозамещения, появилась необходимость в выстраивании инфраструктуры на базе государственных требований к решениям в области информационной безопасности. Одним из таких решений является организация доступа клиентов к веб-ресурсам через портал nGate по защищённому TLS соединению с использованием шифрования по ГОСТ криптопровайдера «КриптоПро». Для этого необходим собственный центр сертификации.

В данной статье мы рассмотрим установку Standalone Center Authority на базе Windows Server 2019. Если вам будет интересно, могу описать процесс привязки нашего центра сертификации к порталу nGate (спойлер: на самом деле там нет ничего сложного).

Содержание
  1. Вводные данные
  2. Почему Крипто Про JCP зло
  3. Обоснование нужности готового клиента
  4. Запрос на получение сертификата для созданного контейнера ключей
  5. Настройка центра сертификации
  6. Тестовые самоподписанные ключи
  7. Создание контейнера
  8. В носителе токена
  9. В носителе usb flash drive
  10. Создание носителя через графическую оболочку
  11. Работа с Rutoken S и ECP
  12. Процесс настройки
  13. Настройка PATH
  14. Выдача контейнера PKCS12
  15. Резюме
  16. Как мы можем грубо заставить Крипто Про отдать ключи
  17. Установка сетевого ответчика (Online responder)
  18. Настройка OCSP — сетевого ответчика (Online responder)
  19. Установка Карма
  20. Инициализация XML-подписи в Santuario
  21. Альтернативный метод получения тестового сертификата
  22. Получение тестового сертификата с помощью cli
  23. Выдача запроса на получение сертификата
  24. Подготовка OpenSSL для работы с ГОСТ
  25. Установка центра сертификации (Standalone CA Windows Server 2019)
  26. Настройка веб-сервера IIS
  27. Что нужно допилить в готовом клиенте, чтобы сбежать с Крипто Про
  28. Как мы можем попросить Крипто Про отдать ключи (на самом деле, нет)
  29. Disclamer
  30. Теперь приступаем к выпуску сертификата
  31. JaCarta-2 PKI/ГОСТ
  32. Выдача контейнера JKS

Вводные данные

КриптоПро NGate — это универсальное высокопроизводительное средство криптографической защиты сетевого трафика, объединяющее в себе функционал:

  • TLS-сервера доступа к веб-сайтам;
  • Сервера портального доступа;

NGate обладает широкими возможностями по управлению доступом удалённых пользователей как с обеспечением строгой многофакторной аутентификации, так и прозрачно, обеспечивая при этом гибкое разграничение прав доступа к ресурсам. КриптоПро NGate реализует российские криптографические алгоритмы, сертифицирован по требованиям к СКЗИ, имеет сертификаты ФСБ России по классам КС1, КС2 и КС3 и может использоваться для криптографической защиты конфиденциальной информации, в том числе персональных данных, в соответствии с требованиями российского законодательства по информационной безопасности.

Кроме того, NGate:

  • Снижает нагрузку по обработке TLS-соединений с веб-серверов, позволяя им сосредоточиться на выполнении своих основных задач;
  • Исключает необходимость установки на каждом веб-сервере отдельного СКЗИ и проведения исследований по оценке влияния ПО веб-серверов на СКЗИ.

Почему Крипто Про JCP зло

  • Если у вас много разработчиков и виртуальных машин, покупать лицензию не очень хочется
  • На Java 8 под OSX завести не удалось (никакую версию КП JCP). Скорей всего это исправят довольно скоро, т.к. представители отреагировали на мой пост в Фейсбуке
  • Вообще, на OSX завести не удалось. Гуй админки — полурабочий, сыпет ошибками, куски гуя не работают.
  • На линуксе тоже есть баги в интерфейсе
  • Когда-то давно установщик на Windows писал в консоли крокозябры (не проверял на новых версиях — может, пофиксили)
  • Установка патчингом дистрибутива джавы. Ящетаю, что установка софта методом патчинга джавы — это зло в последней инстанции, за это суд по правам человека должен назначать шестикратный расстрел с повешанием
  • Не каждую джаву можно пропатчить, для выяснения магической комбинации нужно серьезно упороться. Тут важно, что мы стараемся разрабатывать на самых новых версиях джавы, с пылу-с жару, и тестируем на новых версия (на момент написания статьи — JDK9), так что ограничения на версию джавы — это безумие как оно есть
  • Способы инсталляции и запуска админки — лютый треш (это надо видеть)

В качестве альтернативы в тестовом окружении я предалагю использовать Bouncy Castle с контейнером PKCS12 или JKS. Это открытое, свободное и бесплатное ПО. К чести разработчиков Крипто Про, похоже, они принимали участие в его разработке.

Для подключения клиента NGate к шлюзу NGate нужно
установить доверенный корневой сертификат
удостоверяющего центра (УЦ), выпустившего
серверный мандат шлюза NGate. Для подключения к тестовому шлюзу NGate необходимо
установить корневой сертификат одного из тестовых УЦ КриптоПро. Для подключения к рабочему шлюзу NGate
необходим соответствующий сертификат УЦ, обратитесь к Администратору безопасности
вашей сети для получения сертификата.

Установка корневого сертификата может быть произведена тремя способами: при помощи
графической утилиты cptools – Инструменты КриптоПро, консольной утилиты
certmgr или клиента NGate. В данном разделе рассматривается
вариант установки корневого сертификата УЦ с использованием клиента NGate.

  • ОСТОРОЖНО: Тестовый УЦ предназначен только для
    целейтестированияи не должен использоваться для других
    целей!
  • Запустите клиент NGate. Перейдите на вкладку
    Сертификаты. Нажмите кнопку Импорт
    для запуска процедуры импорта корневого сертификата.
  • Выберите в диалоговом окне Мастера установки сертификата Сертификат УЦ,
    нажмите Далее.
  • Выберите и откройте ранее скачанный файл сертификата.
  • Подтвердите действие в возникшем предупреждении безопасности при процедуре
    импорта

Криптопро не видит контейнер на Rutoken S

По просьбам трудящихся публикую инструкцию “выпускаем себе тестовые сертификаты крипто-про как горячие пирожки!”. Здесь описан процесс получение сертификата квалифицированной электронной подписи (КЭП) содержащего любые данные (OID) на тестовом удостоверяющем центре КриптоПро.

Изначально предполагается, что у нас уже установлен CryptoPro CSP и КриптоПро ЭЦП Browser plug-in, если нет, то идем качаем на официальный сайт. Все операции будут описаны относительно работы в ОС Linux. В MacOS и Windows, в принципе, не должно быть существенных отличий, кроме поправки на пути к исполняемым файлам.

Так же необходимо наличие действительного сертификата тестового УЦ КриптоПро в корневом хранилище сертификатов. Проверить его наличие можно командой

/opt/cprocsp/bin/amd64/certmgr -list -store uRoot

В выводе должно быть что-то вроде

sudo /opt/cprocsp/bin/amd64/certmgr -inst -store uRoot -file /tmp/certnew. cer

Обоснование нужности готового клиента

На технологическом портале СМЭВ3 лежат исходники клиента, но вот незадача — они гвоздями прибиты к КриптоПро. Вордовский файл с инструкцией, приложенный к исходникам, утверждает это самым прямым образом. Да и все равно, исходные ключи у нас тоже в формате КриптоПро. Исходя из production это нормально, а вот для тестового окружения жутко неудобно. Хотелось бы от этого избавиться.

На сайте есть две версии — “актуальная” и “рекомендуемая”. Почему они так, и почему актуальная версия не рекомендуется, а рекомендуемая не актуальна — какая-то дилемма копирайтера 🙂 Дальше речь о том клиенте который “актуальный”.

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

Криптопро не видит контейнер на Rutoken S

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

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

Основная претензия к документации — это канцеляризмы и скудное описание в интернете. Помните мем про копирайтера, который из абзаца сделал одно предложение в несколько слов? Для документации СМЭВа это имеет место быть, например вот цепочка рефакторинов для одной произовльно взятой фразы:

ИС потребителя направляет в СМЭВ межведомственный запрос;”
“2. ИС потребителя направляет в СМЭВ запрос;”
“2. ИС потребителя направляет запрос;”
“2. потребитель направляет запрос;”
“2. запрос потребителя;”

Короче, наличие готовой реализации — это добро.

Запрос на получение сертификата для созданного контейнера ключей

Для создания запроса на получение сертификата для контейнера ‘имя_контейнера’ , воспользуемся командой:

В параметре -dn указываются данные, которые будут хранится в поле Subject сертификата.

В параметре -hashalg указывается алгоритм хэширования. В случае примера использовался  OID 1. 643. 2 – ГОСТ Р 34. 11-12 с длиной 256

-nokeygen – использовать существующие ключи из указанного контейнера;

-both* – создать/использовать оба типа ключей;

Более подробная информация про опции утилиты cryptcp: Инструкция_cryptcp. pdf

Созданный запрос будет сохранен в файле cert. req. Эти данные нужны для получения сертификата в удостоверяющем центре.

Для примера можно воспользоваться тестовым  удостоверяющим центром КриптоПро. Нам нужен пункт ” Отправить готовый запрос PKCS#10 или PKCS#7 в кодировке Base64 “. На следующей странице в поле «Сохраненный запрос» вставляем содержимое файла cert. req и нажимаем кнопку «Выдать».

Читайте также:  ЭЦП для Министерство финансов Российской федерации

Для просмотра содержимого cert. req, воспользуйтесь командой: $ cat  cert. req

После чего следует загрузить сертификат и цепочку сертификатов:

Криптопро не видит контейнер на Rutoken S

  • Установить сертификат УЦ:/opt/cprocsp/bin/*/certmgr -inst -crl -file <имя_файла_с_сертификатом_УЦ>l -store CA
  • Добавить цепочку сертификатов:/opt/cprocsp/bin/*/certmgr -inst -file <имя_файла_с_цепочкой_сертификатов> -store uRoot
  • Установить сам сертификат:/opt/cprocsp/bin/amd64/certmgr -inst -file <имя_файла_с_полученным_сертификатом> -cont <имя_контейнера>

Для записи полученного сертификата в контейнер следует воспользоваться командой:

/opt/cprocsp/bin/amd64/csptest -keys -cont <имя_контейнера> -keyt exchange -impcert <имя_файла_с_полученным_сертификатом>

Криптопро не видит контейнер на Rutoken S

С помощью опции -certusage можно указать OID назначение сертификата

Назначение сертификата представляется в сертификате объектным идентификатором, присвоенным этой политике, – OID. Если в сертификате указано несколько политик, то это означает, что сертификат соответствует всем этим политикам списка.

1может использоваться как сертификат серверной аутентификации1. 2может использоваться как сертификат клиентской аутентификации1. 3может использоваться для электронной подписи кода1. 4может использоваться для защиты электронной почты (электронная подпись, шифрование, key agreement)1. 8может использоваться для включения значения хэш-функции при создании штампа времени на документы в Службе штампов времени1. 9может использоваться для формирования электронной подписи OCSP-запросов

* Объектные идентификаторы (OID) определяют отношения, при осуществлении которых электронный документ, подписанный ЭЦП, будет иметь юридическое значение. OID, зарегистрированные в Удостоверяющем центре, включаются состав следующих расширений сертификата ключа подписи: Key Usage (использование ключа), Extended Key Usage (расширенное использование ключа), Application Policy (политики применения сертификата).

Настройка центра сертификации

В «Диспетчере серверов (Server manager)» – выбираем «Служба сертификации Active Directory (AD CS) – правой клавишей по вашему серверу и открываем: «Центр сертификации (Certification Authority).

Вы попали в оснастку управления центром сертификации: certsrv.

Выбираем ваш центр сертификации и открываем свойства (рис. 10):

Криптопро не видит контейнер на Rutoken S

Рисунок 10. Настройка центра сертификации. Оснастка управления центром сертификации certsrv.

Следующим важным шагом выступает настройка точек распространения CDP и AIA.

Authority Information Access (AIA) — содержит ссылки на корневой сертификат центра сертификации (Certification Authority)

CRL Distribution Point — содержит ссылки на файлы CRL, которые периодически публикует сервер CA, который издал рассматриваемый сертификат. Этот файл содержит серийные номера и прочую информацию о сертификатах, которые были отозваны. (рис. 11)

Мы используем веб-сервер, который доступен как внутри сети, так и из интернета (так как сертификаты могут использоваться пользователями интернета) по одному и тому же URL.

В разделе свойства переходим в «Расширения (Extensions):

Удаляем ненужные точки распространения и оставляем локальную и внешнюю ссылку для CDP:

Ставим галочки «Включить в CRL. Включить в CDP (Include in CRL. Include in the CDP)».

Ставим галочку: «Включать в AIA- расширение выданных сертификатов (Include in the AIA extension of issued certificates)»

Ставим галочку: «Включать в расширение протокола OCSP (Include in the online certificate status protocol (OCSP) extension)»

Криптопро не видит контейнер на Rutoken S

Криптопро не видит контейнер на Rutoken S

Рисунок 11. Настройка точек распространения AIA и CRL

В свойствах центра сертификации можно настроить автоматический выпуск сертификатов при поступившем запросе. Так вы исключаете возможность проверки указанных требуемых полей сертификатов. Для этого перейдите в «Модуль политик (Policy Module)» — «Свойства (Properties)» и выберите соответствующий пункт:

В первом случае сертификату присваивается режим ожидания, а одобрение выпуска сертификата остается за администратором;

Во втором случае из-за отсутствия шаблонов в Standalone CA сертификаты будут выпускаться автоматически. (рис. 12)

Криптопро не видит контейнер на Rutoken S

Криптопро не видит контейнер на Rutoken S

Рисунок 12. Дополнительные настройки ЦС для автоматического выпуска сертификатов

Да, центр сертификации уже функционирует и доступен по указанному dns-имени. Не забудьте открыть 80 и 443 порты для функционирования веб-сервера и online-reposnder’a, настройкой которого мы займёмся далее.

При переходе по ссылке извне в IE необходимо добавить наш веб-сервер в «Надежные сайты (Trusted Sites)» в настройках в пункте «Безопасность». Не забудьте, что должен быть установлен КриптоПро CSP, в ином случае при выпуске сертификата вам не будет доступен выбор ГОСТовского криптопровайдера (рис. 13).

Криптопро не видит контейнер на Rutoken S

Рисунок 13. Веб-интерфейс центра сертификации. Формирование запроса. Правильное отображение

Вернёмся в оснастку certsrv к нашему центру сертификации и настроим выпуск разностных CRL. Для этого необходимо открыть «Свойства (Properties)» раздела «отозванных сертификатов (Revoked Certificates)» (рис. 14).

Задаём «Интервал публикации CRL (CRL Publications interval)».

Включаем публикацию разностных CRL и задаём интервал.

Кажется, что все хорошо. Но есть один момент:

Выполните следующую команду в power shell:

Криптопро не видит контейнер на Rutoken S

Рисунок 14. Настройка параметров публикации CRL.

Тестовые самоподписанные ключи

Так как мы деламем все это в тестовых целях, теперь мы подходим к кульминации и начинаем сами себе выдавать ключи.

  • Все действия производить на Windows (подойдет виртуальная машина) с установленным Крипто Про CSP;
  • Щелкнуть по ссылке “Создать и выдать запрос к этому ЦС”;
  • Заполнить необходимые поля;
  • Нажат кнопку “Выдать”;
  • Установить сертификат.

Создание контейнера

Для создания контейнера в носителе HDIMAGE следует воспользоваться командой:

/opt/cprocsp/bin/amd64/csptest -keyset -newkeyset -cont ‘\. HDIMAGEимя_контейнера’

Если локального носителя не существует, то его можно создать командой:

sudo /opt/cprocsp/sbin/amd64/cpconfig -hardware reader -add HDIMAGE store

HDIMAGE размещается на /var/opt/cprocsp/keys/<имя пользователя>/

В носителе токена

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

/opt/cprocsp/bin/amd64/csptest -keyset -newkeyset -cont ‘\. Aktiv Rutoken ECP 00 00имя_контейнера’

Название токена может отличаться. Для идентификации воспользуйтесь командой: csptest -card -enum -v -v

В носителе usb flash drive

/opt/cprocsp/bin/amd64/csptest -keyset -newkeyset -cont ‘\. FLASHимя_контейнера’

Создание носителя через графическую оболочку

В 5-ой версии КриптоПРО CSP v. 0, для создания контейнера, имя носителя можно не указывать, а выбрать в интерактивном gtk-диалоге:

/opt/cprocsp/bin/amd64/csptest -keyset -newkeyset -cont ‘имя_контейнера’

Криптопро не видит контейнер на Rutoken S

Криптопро не видит контейнер на Rutoken S

Работа с Rutoken S и ECP

Работа с Рутокен S и ECP аналогична, поэтому все дальнейшее описание будет на примере работы с Рутокен S.

Вставить Rutoken S в разъем USB и проверить, определяется ли он , а так же его имя :

В случае ошибки типа ERROR: ScardListReaders(NULL) следует перезапустить pcscd:

sudo service pcscd restart

Открыть Пуск — Утилиты — Инструменты КриптоПро — Показать расширенные — Управление носителями. Носитель должен н а вкладке считыватель.

Криптопро не видит контейнер на Rutoken S

Создать контейнер с именем eos на Rutoken S:

csptest -keyset -provtype 80 -newkeyset -cont ‘\. Aktiv Co. Rutoken S 00 00eos’

где Aktiv Co. Rutoken S 00 00 — это имя подключенного по USB Рутокена.

В открывшемся графическом окне следует перемещать указатель мыши или нажимать клавиши для генерации случайной последовательности до завершения операции.

Во всплывающем окне ввести pin-код для контейнера (по умолчанию — 12345678), нажать OK.

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

Выдача запроса на получение сертификата осуществляется в соответствии с примечанием ниже.

Для выдачи запроса на получение сертификата и загрузки цепочки сертификатов см. Выдача запроса на получение сертификата.

В поле Сохраненный запрос вставить содержимое из файла test. req.

Так же установить по инструкции расширение КриптоПро ЭЦП Browser plugin, если это не было сделано ранее.

Установить certnew. p7b в личное хранилище Rutoken S:

certmgr -inst -file certnew. p7b -store uMy -cont ‘\. Aktiv Co. Rutoken S 00 00eos’ -inst_to_cont

Предполагается, что файл certnew. p7b находится в том же каталоге, где выполняется запрос.

Если Rutoken S был получен уже с контейнером «Crypto Pro» и полученным сертификатом, записать в хранилище сертификатов CryptoPro информацию об этом сертификате:

csptestf -absorb -cert -pattern ‘rutoken’

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

Процесс настройки

Ранее я не сталкивался с центрами сертификациями. Поскольку ОС Windows Server мне ближе, решил развернуть ЦС с использованием Server Manager. Разворачивать контроллер домена не нужно, так как сертификаты будут выдаваться внешним пользователям. Соответственно, можно обойтись «автономным» центром сертификации, подробнее о нём расскажу позже.

Перед развертыванием центра сертификации необходимо:

  • Установить СКЗИ КриптоПро CSP 5.0.12330:
  • Установить КриптоПро ЭЦП Browser plug-in;

Инсталляцию производим через «Дополнительные опции»

  • Выбираем язык установки, уровень защиты КС1 (другие уровни защиты требуют дополнительных аппаратных средств защиты);
  • В разделе «Установка компонентов» проверяем, что добавлен «Криптопровайдер уровня ядра ОС»; (рис. 1)

Криптопро не видит контейнер на Rutoken S

Рисунок 1. Установка дополнительных компонентов «КриптоПро CSP»

Криптопровайдер уровня ядра ОС необходим для работы криптопровайдера в службах и ядре Windows.

В следующем окне оставляем пункты:

  • Зарегистрировать считыватель «Реестр» (позволит сохранять контейнеры ключей в реестр);
  • Усиленный контроль использования ключей;
  • Не разрешать интерактивные сервисы Windows;

Также «КриптоПро» предложит добавить сертификаты своих центров сертификации;

Устанавливаем, перезагружаемся.

Настройка PATH

Для дальнейшей работы добавить в путь поиска исполняемых файлов каталоги Карма:

Вся дальнейшая настройка и работа должны происходить в терминальной сессии, в которой в переменную PATH добавлены каталоги Карма.

Выдача контейнера PKCS12

В принципе, это не особо нужно, потому что у нас уже есть простой и удобный способ выдавать JKS, а JKS для Java это самое что ни на есть родное решение. Но для полноты картины, пусть будет.

  • Подготовить OpenSSL с ГОСТом по инструкции (есть в этой статье).
  • GOST2001-md_gost94 hex (если надо):openssl.exe dgst -hex -sign private.key.pem message.xml
  • MIME application/x-pkcs7-signature (если надо):openssl smime -sign -inkey private.key.pem -signer crt.crt -in message.xml
  • Превратить pem в pkcs12:openssl pkcs12 -export -out private.key.pkcs12 -in private.key.pem -name “alias”

Резюме

В результате всех вышеописанных действий мы получили относительно легий способ избавиться от тяжкой ноши Крипто Про.

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

Как мы можем грубо заставить Крипто Про отдать ключи

Вот тут наступает момент “это радость со слезами на глазах”. Некая контора под названием Лисси Софт, всего за 2 тыщи рублей отдает нам гениальную утилиту P12FromGostCSP. Ее создатели таки победили ту проблему, которую не осилило сообщество, и она выдирает ключи в PFX. Радость — потому что она работает.

Читайте также:  криптопро csp воронеж

Со слезами — потому что это проприетарщина, и она фиг знает как работает. На картинке Ричард Столлман как бы удивляется и спрашивает: “неужели вы боретесь с проприетарщиной с помощью другой проприетарщины?”

Криптопро не видит контейнер на Rutoken S

Так что целиком инструкция по перегону ключей выглядит как-то так:

  • Все действия производить на Windows (подойдет виртуальная машина) с установленным Крипто Про CSP;
  • Подготовить OpenSSL с ГОСТом по инструкции (есть в этой статье).
  • Купить P12FromGostCSP. Поплакать.
  • Установить исходный ключ в КриптоПро (это заслуживает отдельной инструкции, но она гуглится).
  • Запустить P12FromGostCSP (перед этим спрятать икону Ричарда Столлмана под стол, чтобы он не проклял тебя за запуск проприетарщины)
  • Выбрать установленный сертификат, указать пароль сертификата КриптоПро
  • Указать произвольный новый пароль (парольную фразу) для ключевой пары PFX
  • Указать местоположение для сохранения файла. Файл лучше именовать в формате p12.pfx (это название по-умолчанию, лучше не трогать — говорят, есть баги, если переименовать)
  • Получить pem файл:openssl pkcs12 -in p12.pfx -out private.key.pem -name “alias”
  • (-name “alias” — эта опция поменяет имя ключа внутри контейнера. Это нужно потому, что P12FromGostCSP именует ключи как попало (на самом деле, по порядку, цифрами), без сохранения исходного алиаса.
  • Получить pkcs12 файл:openssl pkcs12 -export -out private.key.pkcs12 -in private.key.pem -name “alias”
  • Готово

Установка сетевого ответчика (Online responder)

А вот мы и вернулись к установке автоответчика.

Добавляем роль в «Диспетчере серверов» (Server Manager) – «Далее (Next)»

Установка ролей и компонентов (Add roles and features wizard)» – «Далее (Next)»;

«Роли сервера (Server roles), раскрываем роль: Служба сертификатов Active Directory (Certificate Services Active Directory); и устанавливаем галочку на «Сетевой ответчик» (Online Responder)

Завершаем работу с мастером ролей и компонентов, путём односмысленных нажатий «Далее (Next)».

В IIS была добавлена Applications: ocsp. Только не пугайтесь, что сама по себе директория пустая. Так и должно быть.

Нам осталось настроить центр сертификации и выпустить сертификат на OCSP.

Настройка OCSP — сетевого ответчика (Online responder)

Так как у Standalone центра сертификации нет шаблонов, нам необходимо вручную сформировать запрос и выпуск сертификата для конфигурации отзыва (Array configuration) в «Управление сетевым ответчиком (Online responder management). Для это используйте следующую конфигурацию для формирования запроса

Создайте: ocsp. txt cо следующим внутренним содержанием:

Откройте командную строку cmd. Перейдите в директорию с текстовым файлом или в будущем просто укажите полный путь при формировании запроса.

Узнаем, на какой срок сейчас выпускаются сертификаты. Для этого воспользуемся командой – certutil –getreg caalidityperiodunits

Результат — на рис.

Криптопро не видит контейнер на Rutoken S

Рисунок 15. В текущей конфигурации сертификаты выпускаются на один год

Изменим длительность выпуска сертификата:

#Изменение выпуска сертификатов с текущего состояния на длительность в 5 лет
certutil -setreg caValidityPeriodUnits 5
#Перезапуск сервера
net stop certsvc
net start certsvc

Сформируем запрос и выпустим сертификат для сетевого автоответчика (рис 16

Во время конфигурирования запроса выбираем место хранения контейнера ключа и проходим процедуру ДСЧ.

Криптопро не видит контейнер на Rutoken S

Рисунок 16. Выпуск сертификата для сетевого автоответчика

Экспортируем сертификат из центра сертификации и устанавливаем его в личные сертификаты локального компьютера.

После запроса сертификата открываем оснастку: Certificates (Run – MMC – Add or remove Snap-ins – Certificate),

Выбираем сертификат, выданный для сетевого ответчика. Нажимаем правой клавишей и открываем «Все задачи (Управление закрытыми ключами (All Tasks – Manage Private keys)».

Это нужно сделать, так как служба OCSP работает от лица Network Service.

Криптопро не видит контейнер на Rutoken S

Рисунок 16. Настройка сертификата для  работы сетевого ответчика

Далее переходим в настройки самого сетевого ответчика. (рис. 17)

Нам необходимо добавить «Конфигурацию отзыва (Revocation Configuration) – «Добавить»

Предстоит небольшой процесс настройки конфигурации отзыва.

Введите имя конфигурации – «Далее».

Выбираем второй пункт: «Выбрать сертификат в локальном хранилище сертификатов (Select a certificate from the local certificate store)» – «Далее».

В следующем окне нажимаем «Обзор (Browse)» и выбираем корневой сертификат нашего ЦА – «Больше вариантов (More choices)». (рис. 17) – «Далее».

В следующем окне выбираем «Выбрать сертификат подписи вручную (Manually a signing sertificate)

Криптопро не видит контейнер на Rutoken S

Рисунок 17. Управление сетевым ответчиком. (online responder management)

Криптопро не видит контейнер на Rutoken S

Рисунок 18. Прикрепляем конфигурации корневой сертификат ЦА

Осталось прицепить к нашей конфигурации выпускаемый ранее сертификат и проверить некоторые моменты.

Переходим в «Конфигурацию массива(array configuration)», выбираем конфигурацию и нажимаем «Назначить сертификат подписи (Assign Signing Certificate)». В появившемся окне нужно просто нажать «ОК».

Теперь необходимо «Обновить конфигурацию массива». Для этого выбираем «Конфигурация массива (Array configuration) – «Обновить (Refresh)»

После всех этих действий главное окно оснастки ocsp должно выглядеть так, как на рисунке 19.

Криптопро не видит контейнер на Rutoken S

Рисунок 19. Итоговый результат о работе сетевого ответчика

В процессе самостоятельной настройки «сетевого ответчика» может возникнуть много вопросов, особенно если нет опыта работы с Standalone центром сертификации, в котором отсутствуют шаблоны, без которых можно обойтись, но пути становятся длиннее в исполнение. Кстати говоря, если после прикрепления сертификата вы не получили заветное Working, то проверьте следующее (рис. 20, 20. 1):

Криптопро не видит контейнер на Rutoken S

Рисунок 20. Переходим в редактирование свойств конфигурации отзыва

Криптопро не видит контейнер на Rutoken S

Рисунок 20. Проверяем что в разделе «Подписи» выбран ГОСТ алгоритм шифрования

Чтобы проверить работу центра сертификации и сетевого автоответчика, выпустите сертификат для конечного пользователя, установите его и экспортируйте в какую-нибудь директорию. А после воспользуйтесь утилитой: Certutil –url /patch/test. crt

Для подробного отчёта вы можете воспользоваться: certutil –verify –urlfetch /patch/test. crt

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

Что ещё интересного есть в блоге Cloud4Y

Установка Карма

  • Создать временный каталог и сделать его текущим:
  • Это можно сделать командами:Версия Карма может быть повышена. При установке новой версии заменить в командах имена архива и пакетов на соответствующие.
  • Распаковать полученный архив командой:
  • Установить пакеты командой:sudo dpkg -i Linux/carma-common_*-astra_amd64.deb Linux/carma-dev_*-astra_amd64.deb Linux/carma-capilite_*-astra_amd64.deb
  • После завершения установки можно удалить содержимое временного каталога, в любом случае оно будет автоматически удалено при перезагрузке.

Инициализация XML-подписи в Santuario

Ах да, тут есть один интересный момент. В сети множество советов, касающихся СМЭВа, заключающихся в ручном парсинге кусков XMLек, и прочим закатом солнца вручную, но это не наш метод (и не метод, который использовали создатели клиента)

Замес в том, что сгенерить самоподписанные ключи по госту легко (копипаста на SO ищется за секунды). А вот подписать — нет, ибо по мнению интернет-школьников якобы Bouncycastle не поддерживает xml-подпись. Конкретней, при работе с Apache Santuario, XMLSignature из santuario-xmlsec не понимает что использовать для обработки метода “xmldsig-more#gostr34102001-gostr3411” при вызове xmlSignature. sign(privateKey).

Отдельная хохма в том, что IntelliJ IDEA Community глючит при попытке отдебажить xmlsec, бросая step in отладчика в неверное место верных исходников. Я попробовал все разумные версии Идеи, поэтому понимать как это работает надо вслепую, написуя тактические письма в Спортлото. Это не в укор Идее, не существует идеальных инструментов, просто фактор повлиявший на скорость понимания вопроса.

Чтобы это заработало, нужно:

Инициализация раз за всю жизнь приложения (н-р в синглтон-бине спринга):

2) Загрузить провайдер, чтобы не патчить JDK:

Security. addProvider(new BouncyCastleProvider());

3) Впердолить в рантайм только что написанный класс:

4) Достучаться до маппингов алгоритмов JCE:

5) Замапить метод на алгоритм:

6) Применить маппинги:

org. apache. xml. security. Init. init();
JCEMapper. init(rootElement);

6) PROFIT!
После этого XMLSignature резко начинает понимать этот метод, и начнет делать xmlSignature. sign.

Альтернативный метод получения тестового сертификата

1) Перейдите на сайт Тестового Удостоверяющего центра ООО “КРИПТО-ПРО”

2) Для получение сертификата, перейдите в раздел Сформировать ключи и отправить запрос на сертификат

3) Заполните идентифицирующие сведения:

Криптопро не видит контейнер на Rutoken S

4) Нажмите “Выдать”, после чего выйдет GTK-окно для создания случайных последовательностей:

Криптопро не видит контейнер на Rutoken S

5) После чего, CryptoPro CSP потребует вести новый пароль для контейнера

6) Тестовый УЦ КриптоПро уведомит нас о том, что сертификат выдан

Криптопро не видит контейнер на Rutoken S

7) Пройти по ссылке и установить сертификат, введя пароль контейнера.

8) После успешной установки сертификата, следует перейти на страницу проверки создания электронной подписи CAdES-BES

Криптопро не видит контейнер на Rutoken S

Для отображения информации о сертификате, Вам необходимо установить сертификат из ридера в локальное хранилище uMy, как указано в 5 главе.

Получение тестового сертификата с помощью cli

Для запроса, получения и установки сертификата с тестового УЦ “КриптоПро”  – можно, воспользоваться одной командой:

Создать контейнер с именем test в локальном хранилище HDIMAGE:

csptest -keyset -provtype 80 -newkeyset -cont ‘\. HDIMAGE est’

В открывшемся графическом окне следует перемещать указатель мыши или нажимать клавиши для генерации случайной последовательности:

Откроется следующее окно:

По запросу ввести пароль для контейнера или оставить это поле пустым, нажать
OK.

Выдача запроса на получение сертификата

Откроется окно, где в поле Сохраненный запрос вставить содержимое из файла *. req, в нашем случае — eos. req.

—–BEGIN NEW CERTIFICATE REQUEST—–и—–END NEW CERTIFICATE REQUEST—–

Криптопро не видит контейнер на Rutoken S

Нажать кнопку Выдать.

Далее загрузить файл, нажав на Загрузить цепочку сертификатов (по умолчанию предлагается имя certnew. p7b).

Выбрать пункт Загрузка последнего базового CRL.

Установить скачанный certnew. p7b-сертификат клиента. При запросе ввести пароль на контейнер \. HDIMAGE est.

, что certnew. p7b находится в каталоге, где выполняется команда. В случае, если сертификат находится в другом месте, указать полный.

certmgr -inst -file certnew. p7b -store uMy -cont ‘\. HDIMAGE est’ -inst_to_cont

Подготовка OpenSSL для работы с ГОСТ

Если у вас в начале статьи на стене висит OpenSSL, когда-нибудь он точно выстрелит. Так что да, это важный момент, необходимый для осуществления дальнейшего текста.

  • Так как у нас Крипто Про, и на Маке оно не взлетает, нам понадобится виртуальная машина с Windows (можно даже Windows XP), и установленной Криптой
  • Проверить, что в установленной версии есть файл gost.dll
  • В установленном OpenSSL найти файл openssl.cfg
  • В самое начало файла добавить строчку:openssl_conf = openssl_def
  • PROFIT
Читайте также:  Эцп госуслуги возможности

Установка центра сертификации (Standalone CA Windows Server 2019)

Непосредственно перед самой установкой коротко объясню особенности Standalone CA:

  • Не интегрирован с Active Directory (а он нам и не нужен);
  • Публикация сертификатов происходит через запрос на WEB-сайте. Путем автоматического или ручного подтверждения администратором ЦС (ЕМНИП, ЦС предприятия было добавлена такая возможность, не проверял её работу);
  • Пользователь сам вводит идентификационную информацию во время запроса сертификата;
  • Не поддерживает шаблоны сертификатов (из-за этого всплывут некоторые моменты, которые раскрою в процессе развертывания).

Измените имя компьютера до установки роли, после это будет сделать невозможно. «Далее (Next)» (рис. 2):

Криптопро не видит контейнер на Rutoken S

Рисунок 2. Уведомления при установки роли.

Добавляем роль в «Диспетчере серверов» (Server Manager), «Далее (Next)» (рис. 3):

Криптопро не видит контейнер на Rutoken S

Рисунок 3. Интерфейс «Диспетчера устройств» (Server Manager)

«Установка ролей и компонентов (Add roles and features wizard)». Нажимаем «Далее (Next)» – «Далее (Next)»;

«Тип установки: Установка ролей и компонентов (Installation type: Role-based or features-based installation». «Далее (Next)»;

«Выбор сервера (Server selection)». В нашем случае среди предложенных будет один сервер и имя компьютера. «Далее (Next)» (рис. 4);

Криптопро не видит контейнер на Rutoken S

Рисунок 4. «Выбор сервера (Server selection)»

«Роли сервера (Server roles). Здесь необходимо отметить две роли: Служба сертификатов Active Directory (Certificate Services Active Directory), Веб-сервер IIS (Web-server IIS);

Во всплывающем окне перечня нажимаем «Добавить компонент (Add features)» – «Далее (Next)»;

«Компоненты (Features) оставляем как есть — «Далее (Next)» ;

«Служба ролей (Role Services)» ЦС, необходимо выбрать:

  • «Центр сертификации (Certification Authority)»,
  • «Служба регистрации в центре сертификации через Интернет (Certification Authority Enrollment)»;

Сетевой автоответчик (Online responder) добавим уже после развертывания ЦА, в противном случае могут возникнуть проблемы.

В «Служба ролей (Role Services)» веб-сервера оставляем всё предложенное автоматически — «Далее (Next)»;

«Подтверждение (Confirmation).

На этом этапе запустится процесс установки роли.

После установки роли центра сертификации необходимо его настроить(рис. Выбираем:

«Настроить службы сертификатов Active Directory (Configure Active Directory-Certificate Services)

Криптопро не видит контейнер на Rutoken S

Рисунок 5. Уведомление о необходимости настройки центра сертификации

Выбираем установленные службы ролей для настройки (Select role services to configure) ЦС: «Центр сертификации (Certification Authority)», «Служба регистрации в центре сертификации через Интернет (Certification Authority Enrollment)»;

При выборе центра сертификации появится окно выбора ключевого носителя – КриптоПРО CSP, в качестве носителя для создания контейнера cngWorkAround используем хранилище ключей реестра Windows – Реестр. (рис

Криптопро не видит контейнер на Rutoken S

Рисунок 6. Выбор ключевого носителя – КриптоПРО CSP

Указываем вариант установки ЦС (Specify the setup type of the CA): Автономный центр сертификации (Standalone CA). «Далее (Next)»;

Указываем тип ЦС (Specify the type of CA) – Корневой ЦС (Root CA). «Далее (Next)»;

Необходимо создать закрытый ключ ЦС, чтобы он мог создавать и выдавать их клиентам. Для этого выбираем «Создать новый закрытый ключ (Create a new private key)».

В качестве поставщика службы шифрования выбираем один из трёх предложенных (не забывайте, что 2001 год уже устарел) Crypto-Pro GOST R 34. 10-2012 Strong Cryptographic Service Provider с длиной 512 и открытого ключа 1024 бита. (рис

Криптопро не видит контейнер на Rutoken S

Рисунок 7. Выбор криптопровайдера

Укажите имя центра сертификации и суффиксы различающего имени, данные суффиксы будут отображаться в составе сертификата в графе «Издатель (Issuer)».

СN = Certificate Name, O = Organization, L = Locale, S = Street, C = Country, E = E-mail; (рис

Указываем необходимый «срок годности (validaty period)» корневого сертификата (в нашем случае было выбрано 15 лет). «Далее (Next)»;

Указываем расположение баз данных сертификатов (certificate database location). «Далее (Next)»;

В окне «Подтверждения (Confirmation) сверяем введённую информацию – «Настроить (Configure)»

Появится окно выбора носителя для создания контейнера нашего ЦС.

Где хранятся сами контейнеры ключей:

Реестр: (в качестве хранилища ключей используется реестр Windows), путь хранения контейнеров ключей следующий:Ключи компьютера: HKEY_LOCAL_MACHINESOFTWAREWow6432NodeCryptoProSettingsKeys

Далее откроется окно генерации начальной последовательности с помощью биологического ДСЧ. Для генерации случайной последовательности перемещайте указатель мыши или нажимайте различные клавиши.

После введите пароль на доступ к закрытому ключу.

Далее появится окно результатов об успешной установке компонентов (рис

Криптопро не видит контейнер на Rutoken S

Рис. Результаты установки

Настройка веб-сервера IIS

Теперь необходимо выполнить некоторые настройки веб-сервера: прицепить сертификат (самоподписанный или выпущенный нашим же ЦА). Кстати, он уже работает. В качестве примера выпустим самоподписанный сертификат.

Откроем Диспетчер служб IIS (Manager IIS) — Сертификат сервера (Server Certificates) (рис. 9);

В открывшемся окне в панели «Действия (Actions)» выберем – «Создать самоподписанный сертификат (Create Self-Signed Certificate);

Выбираем тип «Личный (Personal) и указываем «Имя сертификата (Friendly Name)»

Криптопро не видит контейнер на Rutoken S

Рисунок 9. Диспетчер служб IIS (IIS Manager)

Также сертификат вы можете выпустить следующим образом:На этой же панели создайте запрос (Create certificate request) для выпуска сертификата через наш ЦА и дальнейшей его загрузки в IIS (Complete Certificate Request). Но это по желанию.

Пример запроса (request) для формирования запроса вручную

В целом с веб-сервером мы закончили, в default web site вы можете увидеть, что были автоматически созданы virtual directory и applications «CertSrv». При желании можно создать отдельную виртуальную директорию под CRL’ки.

Что нужно допилить в готовом клиенте, чтобы сбежать с Крипто Про

Код написан довольно дружелюбно для расширения, поэтому можно просто взять за основу класс KeyStoreWrapperJCP, и аналогично написать KeyStoreWrapperBouncyCastlePKCS12, KeyStoreWrapperBouncyCastleJKS.

Переписать DigitalSignatureFactory, так, чтобы он на вход начал принимать путь до криптоконтейнера на файловой системе и пароль от него (для КриптоПро это просто не нужно). Там есть свич, который проверяет тип криптопровайдера, в него надо дописать дополнительно два кейса, для имен типа BOUNCY_JKS и BOUNCY_PKCS12 и навешать использование соответсвующих KeyWrapper и вызов initXmlSec.

В initXmlSec нужно дописать
1) возможность принимать вообще любой провайдер, а не только криптопро (это просто удобно)
2) Security. addProvider(new BouncyCastleProvider());
3) для XMLDSIG_SIGN_METHOD сделать свич: если КриптоПро, то алгоритм называется “GOST3411withGOST3410EL”, а если BouncyCastle алгоритм называется “GOST3411WITHECGOST3410”.

Ну вроде как и все. Если бы была известна лицензия на этот смэв-клиент, я бы приложил конкретный код под Apache License 2, а так это просто список идей.

Как мы можем попросить Крипто Про отдать ключи (на самом деле, нет)

Если у нас уже есть настоящие (не самоподписанные) ключи, то совершенно некисло было бы проверить их в действии. Да, мы говорим о тестовых целях, но таки доверяй — но проверяй!

Если поставить винду в виртуальную машину, накатить туда Крипто Про, установить ключи и попробовать их экспортировать, то обнаруживаем удивительную вещь: в экспортере не работает экспорт в PKCS12, а все остальные направления в экспортере заблокированы (англ. “grayed out”).

“От Алексея Писинина был получен ответ:
Добрый день. PKCS12 не соответствует требованиям безопасности ФСБ в части хранения закрытых ключей. В теории, закрытые ключи должны храниться на так называемых “съемных” носителях. Собственно, по этой причине и не работает экспорт

Я правильно это читаю как, что у них гуй для экспорта есть, но бизнес-логики к нему нету?!
Ппоэтому каких галочек ни нащелкай — всегда будет выпадать ошибка на последнем шаге гуевого мастера?!

Какой же стыд.

Dear God,
Please kill them all. Love, Greg.

Криптопро не видит контейнер на Rutoken S

Disclamer

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

Недавно мне нужно было разобраться, как написать сервис, работающий с Системой Межведомственного Электронного Взаимодействия. Все написанное представляет собой просто результат небольшого исследования, максимально абстрагированный от выполненной работы. И даже приблизительно угадать что-то о реально принятых решениях невозможно, я проверял.

Теперь приступаем к выпуску сертификата

где в следующих OID должны быть корректные (проходящие по контрольной сумме) данные

643. 131. 1: ИНН
1. 643. 100. 1: ОГРН
1. 643. 100. 5: ОГРНИП
1. 643. 100. 3: СНИЛС

Для КПП нет официального OID, но некоторые используют 1. 643. 100. Другие ГОСТ-овые OID можно посмотреть, например, по ссылке или в документе ФОРМАТ СЕРТИФИКАТА. pdf

Далее жмем Создать запрос на сертификат, соглашаемся со всем и следуем инструкциям от CSP. В результате мы получаем запрос на сертификат (CSR) закодированный в base-64, копируем его в буфер обмена.

На следующей странице обязательно выбираем Base64-шифрование и жмем на ссылку Загрузить сертификат.

Открываем полученный файл в любом редакторе и удаляем —–BEGIN CERTIFICATE—– в начале и —–END CERTIFICATE—– в конце, так чтоб осталось только тело сертификата между ними, и копируем его в буфер обмена.

Возвращаемся на страничку RusCryptoJS, где был создан CSR и вставляем скопированный сертификат в поле Certificate и жмем Записать сертификат. Параллельно можно поглядывать в консоль браузера, если интересно)

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

/opt/cprocsp/bin/amd64/certmgr -list -store uMy

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

JaCarta-2 PKI/ГОСТ

Перейти в ранее распакованный каталог с КриптоПро linux-amd64_deb:

sudo dpkg -i cprocsp-rdr-jacarta-64_5. 1237-4_amd64. deb

Вставить JaCarta-2 PKI/ГОСТ в разъем USB и проверить, определяется ли он, а так же его имя:

Открыть: Пуск — Утилиты — Инструменты КриптоПро — Показать расширенные — Управление носителями. Выберите считыватель.

Криптопро не видит контейнер на Rutoken S

Создать контейнер с именем tok на JaCarta-2 PKI/ГОСТ :

В открывшемся графическом окне следует перемещать указатель мыши или нажимать клавиши для генерации случайной последовательности.

Во всплывающем окне ввести pin-код для контейнера (по умолчанию — 11111111 ), нажать ОК.

В итоге будет создан контейнер.

Криптопро не видит контейнер на Rutoken S

Сохраненный запрос вставить содержимое из файла tok. req.

Установить certnew. p7b в личное хранилище JaCarta-2 PKI/ГОСТ:

Выдача контейнера JKS

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

Оцените статью
ЭЦП Эксперт
Добавить комментарий