Контекст
Эта публикация – практический кейс 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. Ребята помогли мне разобраться в новой для меня области и приложили усилия для того, чтобы общение было результативным. В качестве консультанта мне попался Санчир Момолдаев. Спасибо тебе, Санчир. Юра, Костя, Дима и Никита терпеливо помогли мне с содержанием и формой этого текста. Спасибо команде за поддержку и задачи.
Ссылка на репозиторий
Репозиторий с обезличенным проектом тут.
amnik21
Интересная статья, спасибо!