Настраиваем TLS контекст. КриптоПро в помощь

от автора

Контекст

Эта публикация – практический кейс 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 вариантами:

  • bouncy castle:

    • open source проект, поддерживающий шифрование для Java и C#;

    • после ознакомления с проектом становится понятно, что разработчики CP поучаствовали в развитии проекта, имплементировав в него ГОСТ-алгоритмы. Так они реализовали возможность использовать bouncy castle в CP компонентах; 

  • СryptoPro:

    • компания, которая развивает собственные компоненты для выполнения криптографических операций — создание, проверка ЭЦП, шифрование, генерация ключей и пр.

С технической точки зрения оба подхода к реализации ГОСТ-шифрования хорошо разобраны тут в блоках «Почему КриптоПро 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).

Рис.1

Рис.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). В моем случае, кнопка недоступна. Увы, нет прав.

Рис.2

Рис.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-контекста;

Рис.3

Рис.3

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

Подготовка хранилищ

Начнем с получения доверенных сертификатов, добавленных нами ранее в 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),

Рис.4

Рис.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/...

Полезные ссылки

О чем

Формат

Длительность

Ссылка

1

TLS/SSL. Общая информация о защите сетевых протоколов

Видео

~ 20 минут

Тут

2

TLS/SSL. Шифрование

Видео

~ 20 минут

Тут

Вместо завершения и ссылка на репозиторий

Проект готов. Им можно пользоваться. Успехов в освоении новых горизонтов.

Благодарности

Огромное спасибо поддержке CP. Ребята помогли мне разобраться в новой для меня области и приложили усилия для того, чтобы общение было результативным. В качестве консультанта мне попался Санчир Момолдаев. Спасибо тебе, Санчир. Юра, Костя, Дима и Никита терпеливо помогли мне с содержанием и формой этого текста. Спасибо команде за поддержку и задачи.

Ссылка на репозиторий

Репозиторий с обезличенным проектом тут.


ссылка на оригинал статьи https://habr.com/ru/articles/823974/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *