Контекст
Эта публикация – практический кейс c кратким туториалом по реализации TLS-соединения, на основе российских стандартов шифрования, основанных на компонентах КриптоПро (CP). Статья не содержит рекламы или попытки сподвигнуть к выбору конкретных компонентов. Я столкнулся с задачей реализации шифрованного подключения к системам бюро кредитных историй (БКИ) в части оценки платежеспособности физических лиц. У меня было ограничение — необходимо было использовать КриптоПро (CP). В процессе реализации задачи открыл для себя несколько интересных моментов. Процесс их «открытия» был чарующим и загадочным. Чары мне обеспечил CP, а с загадками помогали службы поддержки БКИ и CP. Этой статьей хочу помочь сэкономить время и сделать прозрачным процесс реализации шифрованного подключения. В начале статьи дам небольшой теоретический экскурс. Если Вас интересуют детали реализации, то сразу переходите к разделу «Установка и настройка CP компонентов», код, приведенный в статье выложен тут. Приятного чтения.
Используемые технологии
Технологический стек:
-
Java 17;
-
Spring Boot 3;
-
Maven;
-
JCP (компонент CP);
-
JCSP (компонент CP);
Какую пользу принесет эта статья
Статья написана для тех, кому необходимо/хочется:
-
Кратко и быстро погрузиться в аспекты шифрованного подключения;
-
Реализовать задачу шифрованного подключения на основе российских стандартов;
-
Использовать компоненты CP;
Про задачу
Задача состоит в реализации интеграции с сервисом проверки кредитного рейтинга физических лиц. Интеграция реализуется на SOAP и должна поддерживать шифрованное подключение на основе российских криптографических стандартов по ГОСТ 28147-89 и ГОСТ 34.12-2015. Сама по себе интеграция не содержит чего-то интересного, чем хотелось бы поделиться. Шифрование на основе криптографических стандартов задача не сложная, но интересная. Сконцентрируемся на ней.
Варианты
Немного порывшись в недрах habr и интернет, сделал вывод, что реализация шифрования на основе криптографических ГОСТ возможна 2 вариантами:
-
-
open source проект, поддерживающий шифрование для Java и C#;
-
после ознакомления с проектом становится понятно, что разработчики CP поучаствовали в развитии проекта, имплементировав в него ГОСТ-алгоритмы. Так они реализовали возможность использовать bouncy castle в CP компонентах;
-
-
-
компания, которая развивает собственные компоненты для выполнения криптографических операций — создание, проверка ЭЦП, шифрование, генерация ключей и пр.
-
С технической точки зрения оба подхода к реализации ГОСТ-шифрования хорошо разобраны тут в блоках «Почему КриптоПро JCP добро» и «Почему КриптоПро JCP зло» с поправкой на то, что на Java 17 и на Linux CP запускается без проблем. Выбор конкретного варианта для большой компании зависит не только от технических аспектов, но и от удобства сопровождения, возможности поддержки, и т.д. В АльфаСтрахование выбор был сделан в сторону CP. Основная причина такого выбора — возможность оперативной квалифицированной поддержки.
CP компоненты
Как ранее было упомянуто, мне понадобились компоненты JCP и JCSP.
-
JCP:
-
Набор библиотек криптографической защиты информации, реализующий российские криптографические стандарты;
-
-
JCSP
-
Набор библиотек реализующих:
-
Формирование и проверку электронной подписи;
-
Шифрование;
-
Другие функции;
-
-
Для использования компонентов вам потребуется их активировать. Сначала работать можно на демо лицензиях (раскрою тему ниже). Затем все необходимое нужно будет закупить.
Немного теории
Создавая эту статью, я руководствовался, в том числе задачей сделать самодостаточное описание, которое будет содержать необходимую и достаточную теорию. В этом блоке я кратко опишу основные принципы и особенности работы TLS/SSL. Те, кто хорошо знаком с темой, что это, зачем оно, и как работает — могут переходить к блоку «Установка и настройка CP компонентов». Если тема TLS/SSL не до конца вам понятна или вызывает интерес, то продолжаем.
Общее
Сетевые устройства реализуют сетевую модель подключения OSI. Один из элементов OSI — уровни сетевого взаимодействия. Эти уровни предлагают модель ответственности сетевых компонентов при взаимодействии внутри сети. Безопасное соединение осуществляется на основе TLS/SSL технологии, которая рассредоточена по транспортному, сеансовому и уровню представления информации. TLS/SSL, по сути — это протоколы безопасной передачи данных по небезопасным сетям:
-
TLS (Transport Layer Security) — протокол защиты транспортного уровня;
-
Фактический стандарт в области шифрования подключения, признанный IETF (Internet Engineering Task Force) с 1999 года
-
-
SSL (Secure Sockets Layer) — уровень защищенных сокетов;
-
Устаревшая технология, которая была основой для разработки TLS;
-
TLS
3 основных аспекта передачи данных, реализуемых TLS:
-
Приватность данных — данные не должен читать тот, кто не авторизован — обеспечивается шифрованием;
-
Шифрование связано с конкретным протоколом, по которому передаются данные;
-
-
Целостность — изменять данные не должен тот, кто не авторизован — обеспечиваются хэш-функциями;
-
Хэш-функция однозначно идентифицирует конкретный передаваемый артефакт;
-
-
Аутентификация — сервер именно тот, за кого он себя выдает — обеспечивается идентификацией;
-
Цифровая подпись, инфраструктура открытых ключей;
-
TLS представляет собой конструктор, который, в зависимости от того, что реализуется для подключения, может поддерживать разные строительные блоки. Для задачи интеграции мне необходимо было реализовать только шифрование трафика. JCP и JCSP были моими кирпичиками.
Шифрование
Основной концепт — ключ шифрования. Ключ шифрования — артефакт, который позволяет зашифровать и/или расшифровать данные с помощью предопределенного алгоритма.
2 основных типа шифрования:
-
Симметричное:
-
Для шифрования и рас-/дешифрования используется один и тот же ключ:
-
Обозначение — разделяемый ключ;
-
Шифровщик/дешифровщик не должны знать значение ключа;
-
Пример симметричного шифрования — шифр цезаря;
-
Распространенные алгоритмы симметричного шифрования — AES, 3DES, RC4, RC5, RC6;
-
-
-
Ассиметричное:
-
Для шифрования и рас-/дешифрования используется разные ключи:
-
Открытый ключ передается. Используется шифрующей стороной;
-
Закрытый ключ скрыт. Используется расшифровывающей стороной;
-
Распространенный алгоритмы ассиметричного шифрования — RSA, DSA. DSS;
-
-
Каждый вид шифрования имеет свои преимущества и недостатки (Таб.1)
|
Вид шифрования |
Преимущества |
Недостатки |
|---|---|---|
|
Симметричное |
Работает быстрее, чем ассиметричное |
Ключ должен храниться в тайне |
|
Ассиметричное |
Открытый ключ может передаваться публично |
Работает медленней, чем ассиметричное |
Может быть использована гибридная модель шифрования. Пример: ассиметричное шифрование для передачи разделяемого ключа, поддерживающего симметричное шифрование и симметричное шифрование для передачи данных. Так, в основном, работа по TLS и реализуется.
Что именно использовали
JCP, JCSP компоненты разработаны в соответствии со спецификацией JCA (Java Cryptography Architecture). JCA поддерживает алгоритм AES.
Если кратко:
-
AES — состоит из нескольких раундов, в каждом из которых над данными совершаются различные операции;
-
Над данными последовательно выполняются — замены (SubBytes), сдвиги строк (ShiftRows), смешивание столбцов (MixColumns) и добавление ключа раунда (AddRoundKey);
-
AES начинается с инициализации начального ключа и данных, которые затем проходят через серию раундов — обычно 10, 12 или 14, в зависимости от длины ключа;
Если подробно про AES.
Установка и настройка CP компонентов
Для того, чтобы у вас была возможность работать с CP-компонентами, необходимо скачать и установить себе соответствующий дистрибутив. Хорошая новость состоит в том, что можно установить себе все необходимое и работать с компонентами без ввода лицензий в течении 90 дней (демо лицензии). Это удобно. Установка не составляет труда. В итоге Вы получаете себе GUI приложение (Рис.1).
Выбранный нами способ работы не потребует больше работать с GUI (почти). Установленный дистрибутив позволит нам использовать CP.
Используемые компоненты и их настройка
У меня на руках были следующие артефакты:
-
Цепочка CER-сертификатов, выданных мне коллегами из БКИ:
-
CER-сертификаты — это сертификаты сервера:
-
Назначение — безопасное соединение между клиентом и сервером;
-
-
PFX-сертификат, выданный мне коллегами из департамента информационной безопасности:
-
PFX (Personal Exchange Formatб PKCS#12) сертификаты содержат частный ключ и соответствующий ему открытый ключ, защищенные паролем;
-
Назначение — безопасное соединение между клиентом и сервером;
-
Работа по использованию этих сертификатов для установки безопасного соединения будет описана дальше.
Импорт CER-сертификатов
CER-сертификаты являются разновидностью CRT-сертификатов. Для их использования под Windows вам нужно:
-
Перейти в следующую директорию, где располагается Ваша JVM —
"[Диск]:\[Пусть до Java]\Java\jdk-17\bin" -
В этой папке среди прочих находится утилита keytool.exe:
-
Назначение — работа с ключами безопасности и цифровыми сертификатами;
-
Она позволяет создавать, импортировать, экспортировать и управлять ключами и сертификатами, генерировать новые пары ключей;
-
-
Из этой папки нужно выполнить следующие команды:
-
Команда →
keytool -import -keystore [путь до cacerts Java. Если в пути есть пробелы, то надо обрамить ""] -alias [название сертификата при импорте] -file [путь до файла с сертификатом] -storepass changeit -noprompt; -
Пример →
keytool -import -keystore "C:\Program Files\Java\jdk-17\lib\security\cacerts" -alias "name" -file c:\Users\user\Desktop\service\сертификаты\XXX_XXX.cer -storepass changeit -noprompt; -
Так Вы импортируете для себя сертификат, который будет использоваться как часть TLS;
-
Рекомендую после того, как Вы выполните импорт, проверить, что сертификат был добавлен в cacerts ->
"keytool -v -list -cacerts storepass changeit"и поискать сертификат по alias;-
Keytool может вернуть успешный ответ, но не добавить сертификат из-за проблем с параметрами команды;
-
-
Если вы работаете и собираете образ для другой операционной системы, то потребуется выполнить аналогичные действия с поправкой на Вашу ОС.
Работа с PFX-сертификатами
PFX содержит сертификат и соответствующий ему секретный ключ. Этот формат используется, чтобы передать содержимое сертификата на конкретное рабочее место. Вот тут про него хорошо и подробно написано. Можно создать и установить сертификат, а так же секретный ключ с помощью утилит управления ключами, следом экспортировать в PFX и импортировать полученный файл в другое хранилище сертификатов. Как вариант, вы можете импортировать этот сертификат себе на рабочее место в реестр сертификатов. В моем случае я имею сформированный и подготовленный сертификат и мне надо добавить его к TLS-компонентам. PFX-компонент может быть подготовлен и установлен на ПО с помощью любого приложения, но именно для использования его вместе с CP, вам потребуется использовать cptools. Выгружаете себе сертификат через экспорт ключей и получаете все необходимое для того, чтобы двинуться дальше (Рис.2). В моем случае, кнопка недоступна. Увы, нет прав.
PFX, как наиболее изменчивая часть нашей интеграции, будет браться из папки ресурсов сервиса. Для активации нам еще понадобится пароль. Сохраним его в корпоративном хранилище данных (в моем случае это vault) и будем использовать в тестовой и продуктивной среде.
Рабочий проект
Подготовка компонентов
Первым шагом поместим в репозиторий артефактов (в моем случае это nexus) библиотеки JCP. Они будут реализовывать шифрование. Для начала скачаем дистрибутивы JCP c сайта CP. Так как я реализовал все на Java 17, то мне нужны дистрибутивы с литерой «-A» в конце названия. Из jcsp понадобятся следующие библиотеки:
-
JCP;
-
JCPRevTools;
-
JCPRevCheck;
-
asn1rt;
-
ASN1P;
-
JCSP;
-
sspiSSL;
Каждую из них нужно будет сложить локально/в nexus для разработки и сборки приложения в тестовом и продуктивном окружениях. С помощью maven команды помещаем библиотеки в nexus:
- Команда: mvn deploy:deploy-file -DgroupId=[указать группу, куда кладем] -DartifactId=[название] -Dversion=[версия] -Dpackaging=[тип упаковывания] -Dfile=[откуда берем] -DrepositoryId=nexus -Durl=[url куда кладем] - Пример: mvn deploy:deploy-file -DgroupId=ru.crypto -DartifactId=cpSSL -Dversion=5.0.45549-A -Dpackaging=jar -Dfile=/c:/Users/user/Desktop/service/java-csp-jcsp.version/nexus/cpSSL.jar -DrepositoryId=nexus -Durl=https://alfastrah.alfastrah.ru/repository/odm-maven-releases
Скрипт нужно применить для каждой библиотеки, которая понадобится. После этого вы можете задействовать их в своем сборщике проекта. В моем случае это maven, поэтому я использую pom. В нем блок с информацией будет выглядеть так:
<properties> <jcsp.version>5.0.45549-A</jcsp.version> </properties> .......................................... <dependency> <groupId>ru.crypto</groupId> <artifactId>JCP</artifactId> <version>${jcsp.version}</version> </dependency> <dependency> <groupId>ru.crypto</groupId> <artifactId>JCPRevCheck</artifactId> <version>${jcsp.version}</version> </dependency> <dependency> <groupId>ru.crypto</groupId> <artifactId>JCPRevTools</artifactId> <version>${jcsp.version}</version> </dependency> <dependency> <groupId>ru.crypto</groupId> <artifactId>ASN1P</artifactId> <version>${jcsp.version}</version> </dependency> <dependency> <groupId>ru.crypto</groupId> <artifactId>asn1rt</artifactId> <version>${jcsp.version}</version> </dependency> <dependency> <groupId>ru.crypto</groupId> <artifactId>JCSP</artifactId> <version>${jcsp.version}</version> </dependency> <dependency> <groupId>ru.crypto</groupId> <artifactId>sspiSSL</artifactId> <version>${jcsp.version}</version> </dependency>
Реализация
Чтобы реализовать TLS-шифрование нам потребуется собрать весь необходимый контекст и имплементировать его при подключении к серверу. Реализация контекста займет 6 компактных классов (Рис.3), логически разделенных по функционалу:
-
Подготовка хранилищ сертификатов;
-
Конфигурация сертификатов и ключей;
-
Подготовка TLS-контекста;
В примерах кода, которые будут располагаться ниже, я сделаю подробное логирование и обработку ошибок, чтобы было однозначно понятно, за что отвечает каждый элемент.
Подготовка хранилищ
Начнем с получения доверенных сертификатов, добавленных нами ранее в cacerts. Для этого мы будем использовать TrustManager. Этот компонент используется для проверки подлинности сертификатов, которыми обмениваются клиент и сервер при установлении защищенного соединения. TrustManager позволяет задавать политики безопасности, которые определяют, каким сертификатам можно доверять, а каким — нет. У нас получится такой конфигурационный компонент Spring:
@Slf4j @Configuration public class CertConfig { /** * Назначение -> * Получение списка доверительных сертификатов * из хранилища сертификатов caserts (Java); */ public List<X509Certificate> getCertsFromCacerts() { TrustManagerFactory trustManagerFactory; try { trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() ); trustManagerFactory.init((KeyStore) null); } catch (NoSuchAlgorithmException | KeyStoreException exception) { log.error( "CertConfig. Ошибка при инициализации trustManager для : {}", exception.getMessage() ); throw new CertException(exception.getMessage()); } List<TrustManager> trustManagers = Arrays.asList(trustManagerFactory.getTrustManagers()); return trustManagers.stream() .filter(X509TrustManager.class::isInstance) .map(X509TrustManager.class::cast) .map(trustManager -> Arrays.asList(trustManager.getAcceptedIssuers())) .flatMap(Collection::stream) .toList(); } }
Следом обработаем добавленный PFX-сертификат. Этот сертификат защищен приватным ключом, который мы используем при запуске приложения. Про то, как получается данный сертификат хорошо написано тут. Сам сертификат положим в папку с ресурсами (рис.4),
а его обработку реализуем в синглотоне с инстансом хранилища ключей в виде конфигурационного компонента, использующего объект с свойствами — PFX (пароль):
@Slf4j @Configuration @EnableConfigurationProperties(value = Pfx.class) @RequiredArgsConstructor public class PFXStore { private KeyStore keyStore; private final Pfx pfx; /** * Назначение -> * Хранилище pfx сертификата; */ public KeyStore getKeyStore() { if (keyStore != null) return keyStore; try { byte[] certByteArray = new ClassPathResource("certs/cert.pfx").getContentAsByteArray(); ByteArrayInputStream is = new ByteArrayInputStream(certByteArray); keyStore = KeyStore.getInstance("PFXSTORE"); keyStore.load(is, pfx.passwordPFX().toCharArray()); } catch ( KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException exception) { log.error( "Store. Ошибка при подготовке хранилища ключей: {}", exception.getMessage() ); throw new PXFStoreException(exception.getMessage()); } return keyStore; } }
Из хранилищ нам осталось подготовить CP-компоненты. Для этого потребуется инициализировать хранилище с типом CP и загрузить в него ранее полученные сертификаты cacerts:
@Slf4j @Configuration @RequiredArgsConstructor public class JcpStore { private final CertStore certStore; /** * Назначение -> * Хранилище гост сертификатов в хранилище на основе JCP; */ public KeyStore prepareKeyStoreWithJcpCert() { KeyStore keyStore; try { keyStore = KeyStore.getInstance(JCP.CERT_STORE_NAME); } catch (KeyStoreException exception) { log.error( "JcpKeyStore. Ошибка при подготовке JCP хранилища: {}", exception.getMessage() ); throw new JcpKeyStoreException(exception.getMessage()); } try { keyStore.load(null, null); } catch ( IOException | NoSuchAlgorithmException | CertificateException exception) { log.error( "JcpKeyStore. Ошибка при инициализации JCP хранилища: {}", exception.getMessage() ); throw new JcpKeyStoreException(exception.getMessage()); } try { for (X509Certificate cert : certStore.getCertsFromCacerts()) { keyStore.setCertificateEntry(UUID.randomUUID().toString(), cert); } } catch (KeyStoreException exception) { log.error( "JcpKeyStore. Ошибка при добавлении гост сертификатов : {}", exception.getMessage() ); throw new JcpKeyStoreException(exception.getMessage()); } return keyStore; } }
Подготовка конфигураций
Сконфигурируем массив доверенных ГОСТ сертификатов, которые понадобятся для установки безопасного соединения:
@Slf4j @Configuration @RequiredArgsConstructor public class TrustManagerConfig { private final JcpStore jcpKeyStore; /** * Назначение -> * Массив доверительных сертификатов гост; */ public TrustManager[] getGostTrustManager() { KeyStore keyStore = jcpKeyStore.prepareKeyStoreWithJcpCert(); TrustManagerFactory factory; try { factory = TrustManagerFactory.getInstance("GostX509"); factory.init(keyStore); } catch (NoSuchAlgorithmException | KeyStoreException exception) { log.error( "TrustManager. Ошибка при инициализации trustManager: {}", exception.getMessage() ); throw new TrustManagerException(exception.getMessage()); } return factory.getTrustManagers(); } }
Затем сформируем список доступных ключей по ГОСТ сертификатам, которые будут объединены в рабочие цепочки. Инициируем CP-компонент (JavaTLSCertPathManagerParameters), который используется для проверки доверия к сертификатам. Добавим к нему подготовленные цепочки сертификатов (PKIX). Нам потребуются собранные из cacerts сертификаты и подготовленное pfx хранилище:
@Slf4j @Configuration @RequiredArgsConstructor public class KeyManagerConfig { private final CertStore certStore; private final PFXStore pfxStore; private final JcpStore jcpKeyStore; /** * Назначение -> * Формирование списка доступных ключей по гост сертификатам; */ public KeyManager[] getGostKeyManagers() { KeyManagerFactory factory; try { factory = KeyManagerFactory.getInstance("GostX509"); } catch (NoSuchAlgorithmException exception) { log.error( "KeyManager. Ошибка при попытке подготовить контейнера: {}", exception.getMessage() ); throw new KeyManagerException(exception.getMessage()); } PKIXBuilderParameters parameters; try { parameters = new PKIXBuilderParameters( jcpKeyStore.prepareKeyStoreWithJcpCert(), new X509CertSelector()); } catch (KeyStoreException | InvalidAlgorithmParameterException exception) { log.error( "KeyManager. Ошибка постороения цепочек сертификации X.509: {}", exception.getMessage()); throw new KeyManagerException(exception.getMessage()); } parameters.setRevocationEnabled(true); try { parameters.setCertStores( Collections.singletonList( java.security.cert.CertStore.getInstance( TYPE_COLLECTION, new CollectionCertStoreParameters( certStore.getCertsFromCacerts())))); } catch ( InvalidAlgorithmParameterException | NoSuchAlgorithmException exception) { log.error( "KeyManager. Ошибка при проверки сертификатов X.509 на отзыв: {}", exception.getMessage()); throw new KeyManagerException(exception.getMessage()); } JavaTLSCertPathManagerParameters managerParameters = new JavaTLSCertPathManagerParameters( pfxStore.getKeyStore(), EMPTY.toCharArray() ); managerParameters.setParameters(parameters); try { factory.init(managerParameters); } catch (InvalidAlgorithmParameterException exception) { log.error( "KeyManager. Ошибка при проверке доверия сертификатам TLS: {}", exception.getMessage()); throw new KeyManagerException(exception.getMessage()); } return factory.getKeyManagers(); } }
Подготовка контекста
Остался последний (почти) шаг. Формирование TLS-контекста. Здесь потребуются подготовленные конфигурации. Несмотря на устаревший термин SSL для наименований в классах javax.net используется именно он. При инициировании контекста зададим актуальный протокол «GostTLSv1.3» и добавим настройку включения контекста по подготовленным нами конфигурациям:
@Slf4j @Configuration @RequiredArgsConstructor public class SSLContextConfig { private final TrustManagerConfig trustManagerConfig; private final KeyManagerConfig keyManagerConfig; /** * Назначение -> * Контекст с готовыми сертификатами и подключениями для * установки безопасного соединения; */ public SSLContext getInstance(boolean isContext) { SSLContext context; try { context = SSLContext.getInstance("GostTLSv1.3"); context.init( isContext ? keyManagerConfig.getGostKeyManagers() : null, trustManagerConfig.getGostTrustManager(), null); } catch (NoSuchAlgorithmException | KeyManagementException exception) { log.error( "SSLContext. Ошибка при формировании SSL контекста: {}", exception.getMessage() ); throw new SSLContextException(exception.getMessage()); } return context; } }
Имплементация контекста
Теперь точно все. При подключении к серверу БКИ зададим наш контекст. Он определяется через HttpClient, который я буду использовать в WebServiceTemplate:
@Configuration @RequiredArgsConstructor public class HttpClientConfig { private final SSLContextConfig contextConfig; public HttpClient prepareHttpClient() { return HttpClients.custom() // set custom context for cryptoPro crypt traffic .setSSLContext(contextConfig.getInstance(true)) .build(); } } ... @Configuration public class WebServiceTemplateConfiguration { private final HttpClientConfig httpClientConfig; private final WebServiceTemplate webServiceTemplate; ... public WebServiceTemplateConfiguration(HttpClientConfig httpClientConfig, ) { this.httpClientConfig = httpClientConfig; this.webServiceTemplate = new WebServiceTemplate(); } public WebServiceTemplate prepareWebServiceTemplateForServiceIncomeSend(String uri) { messageSender.setHttpClient(httpClientConfig.prepareHttpClient()); webServiceTemplate.set...; return webServiceTemplate; } }
Настраиваем свой клиент: добавляем маршаллер, определям uri и т.д. Все! Мы имеем готовое подключение по TLS на основе отечественных алгоритмов ГОСТ-шифрования. Приятного использования.
Что еще будет полезно?
Оцените свои потребности
Я описал основные действия, которые требуются для настройки TLS соединения с помощью компонентов CP. Так вы получаете решение, которое будет формировать контекст используя сертификаты, помещенные в cacerts Java и ресурсные папки проекта. Это универсальное масштабируемое решение. Для его реализации вам нужно будет купить лицензии на компоненты CP. В моем случае было достаточно лицензии на 1 процессор. Если Вы планируете использовать сервис под высокими нагрузками, то имеет смысл посмотреть в сторону более производительных лицензий, информацию о которых можно найти на сайте CP.
Запуск сервиса
Обратите, пожалуйста, внимание на то, что для запуска функционала CP, в main основного application класс требуется добавить немного статических заклинаний, которые отвечают за активацию атрибутов, критичных для функционирования CP компонентов.
Логирование
В процессе разработки и отладки может потребоваться добавить логирование компонентов CP, которое не работает из коробки. Для этого потребуется:
-
Добавить настройки логирования в JVM;
-
Настроить логгер файлы/компоненты, ответственные за логирование Вашего сервиса;
Настройки логирования JVM заключаются в том, что вам надо в файл — «logging.properties.src», который находится по адресу: "С:\[Путь до Java]\Java\jdk-17\lib\", добавить следующее:
ru.CryptoPro.JCP.tools.JCPLogger.level = ALL ru.CryptoPro.ssl.SSLLogger.level=ALL ru.CryptoPro.ssl.SSLLogger.handlers=java.util.logging.ConsoleHandler
Если такого файла нет, то вы можете взять его полностью из примера кода ниже и подложить в свою JVM.
Вторым действием надо пробросить логирование в свой сервис. Для меня это logback и в нем добавленные разрешения выглядят так:
<logger name="ru.CryptoPro.ssl.SSLLogger" level="ALL" /> <logger name="ru.CryptoPro.ssl.SSLLogger" handlers="java.util.logging.ConsoleHandler" /> <logger name="java.util.logging.ConsoleHandler" level="ALL" />
Доступы
После того как разработка будет закончена, логично задуматься о подготовке тестового и прод окружений. От вас потребуется дать доступ к ресурсам CP, на которых проверяется цепочка сертификатов на предмет отзыва/валидности. Если этого не сделать, при попытке выполнить запрос вы будете получать ошибку на невалидность сертификатов. В моем случае доступ потребовался до:
URIName: http://cdp.cryptopro.ru/ra/cdp/... URIName: http://vpnca.cryptopro.ru/cdp/...
Полезные ссылки
Вместо завершения и ссылка на репозиторий
Проект готов. Им можно пользоваться. Успехов в освоении новых горизонтов.
Благодарности
Огромное спасибо поддержке CP. Ребята помогли мне разобраться в новой для меня области и приложили усилия для того, чтобы общение было результативным. В качестве консультанта мне попался Санчир Момолдаев. Спасибо тебе, Санчир. Юра, Костя, Дима и Никита терпеливо помогли мне с содержанием и формой этого текста. Спасибо команде за поддержку и задачи.
Ссылка на репозиторий
Репозиторий с обезличенным проектом тут.
ссылка на оригинал статьи https://habr.com/ru/articles/823974/
Добавить комментарий