Если вы решили разрабатывать приложение на Java + maven, которое должно работать с отечественной криптографией, то эта статья для вас.

В статье рассказывается как создать приложение и подключить к нему JavaCSP для работы с ГОСТ-овой криптографией. В качестве примера мы создадим программу, показывающую все сертификаты в регистре.

Целевая аудитория junior/middle разработчики, которым требуется реализовать подписание/шифрование на базе отечественной криптографии. И которые до этого не имели опыта работы с Крипто Про.

Java CSP - это по сути API, чтобы обратиться к уже установленному в системе Crypto Pro CSP. Сам модуль ничего не подписывает и не шифрует, а лишь обращается к уже установленному в системе Крипто Про.

Если вы уже разрабатывали maven приложения на java, то при необходимости добавить новый модуль в проект добавляли еще одну dependency в pom файл. У крипто про нет публичных maven репозиториев и поэтому потребуются дополнительные действия.

Вначале необходимо скачать Java CSP с официального сайта.

Распаковываете архив в удобном месте и стандартными командами устанавливаете библиотеки в локальный maven репозиторий

mvn install:install-file -Dfile=./libs/JCSP.jar \
-DgroupId=ru.cryptopro.jcp \
-DartifactId=jcp-jscp \
-Dversion=5.0.40363-A \
-Dpackaging=jar \

Необходимый минимум библиотек для установки есть в cprypto-install.sh в репозитории в конце статьи.

После установки в локальный maven репозиторий можно добавлять библиотеки JavaCSP как зависимости в pom файл

<dependency>
   <groupId>ru.cryptopro.jcp</groupId>
   <artifactId>jcp-jscp</artifactId>
   <version>5.0.40363-A</version>
</dependency>

К счастью начиная с java 10 более нет необходимости устанавливать Java CSP непосредственно в jre. Достаточно инициализировать его непосредственно в программе.

System.setProperty("file.encoding", "UTF-8");
Security.addProvider(new JCSP()); // провайдер JCSP
Security.addProvider(new RevCheck());// провайдер проверки сертификатов JCPRevCheck
//(revocation-провайдер)
Security.addProvider(new CryptoProvider());// провайдер шифрования JCryptoP

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

KeyStore ks = KeyStore.getInstance("REGISTRY", "JCSP");
ks.load(null, null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
   Certificate cert = ks.getCertificate(aliases.nextElement());
   if (cert == null) {
       continue;
   }
   if (!(cert instanceof X509Certificate)) {
      continue;
   }
   X509Certificate curCert = (X509Certificate) cert;
   System.out.println(CertUtil.subjectCN(curCert));
}

Остался последний шаг - собрать наше приложение. Обратите внимание - при работе  Java CSP проверяет свои библиотеки на версию и md5 (RevCheck). При сборке “толстого” jar файла RevCheck проверяет версию и md5 всего “толстого” jar файла. Идет сравнение с заложенными в RevCheck значениями. Ну и конечно такая проверка не проходит. Поэтому необходимо собирать “тонкий” jar с внешними библиотеками.

Для этого мы используем maven-dependency-plugin для сборки зависимостей, maven-jar-plugin для сборки самого приложения и maven-assembly-plugin для сборки всего приложения с библиотеками в zip архив.

<build>
   <finalName>${project.name}</finalName>
   <plugins>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-dependency-plugin</artifactId>
           <executions>
               <execution>
                   <id>copy-dependencies</id>
                   <phase>prepare-package</phase>
                   <goals>
                       <goal>copy-dependencies</goal>
                   </goals>
                   <configuration>
                       <outputDirectory>
                           ${project.build.directory}/libs
                       </outputDirectory>
                   </configuration>
               </execution>
           </executions>
       </plugin>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
           <configuration>
               <archive>
                   <manifest>
                       <addClasspath>true</addClasspath>
                       <classpathPrefix>libs/</classpathPrefix>
                       <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                       <mainClass>
                           site.barsukov.java_csp.Application
                       </mainClass>
                   </manifest>
               </archive>
           </configuration>
       </plugin>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-assembly-plugin</artifactId>
           <executions>
               <execution>
                   <phase>package</phase>
                   <goals>
                       <goal>single</goal>
                   </goals>
                   <configuration>
                       <appendAssemblyId>false</appendAssemblyId>
                       <descriptors>
                           <descriptor>src/main/resources/assembly.xml</descriptor>
                       </descriptors>
                       <finalName>${project.artifactId}-${project.version}</finalName>
                       <outputDirectory>${project.build.directory}/distr</outputDirectory>
                   </configuration>
               </execution>
           </executions>
       </plugin>
   </plugins>
</build>

После запуска приложения выводится список установленных в реестре сертификатов. 

Как реализовать подписание, шифрование и пр. вы сможете найти в документации в скачанном ранее с сайта крипто про архиве.

Репозиторий программы

Комментарии (7)


  1. fzn7
    19.08.2021 09:32
    -3

    Все классно, но maven объективно надо уже отправлять на пенсию


    1. victor_2004 Автор
      19.08.2021 10:22
      +3

      Я честно пытаюсь переехать на gradle. Пока с gradle больше проблем отхватываю, чем профита получаю. Это не умеет, тут через ацкий удар в бубен и т.д.

      При этом у gradle нет киллер фичи, чтобы быстро вытеснить maven, как в свое время maven вытеснил ant. Поэтому старые проекты никто переводить с maven не будет. И будем мы этого пенсионера встречать еще долго :-)


      1. artem_larin
        19.08.2021 11:27
        +3

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


      1. MrUndead96
        19.08.2021 19:50
        -1

        В вашем случае достаточно добавить mavenLocal() в репозитории build.gradle и в dependency блоке указать:  implementation('ru.cryptopro.jcp:jcp-jscp:5.0.40363-A')


    1. artem_larin
      19.08.2021 11:25
      +2

      А в чем конкретно мавен "уже не тянет"?


      1. sshikov
        19.08.2021 20:31
        +2

        Да зачем вы слушаете непонятно кого? Скажем, в моей практике я никогда (с начала использования версии 2.0, т.е. после перехода 1.0->2.0) не обновлял мавен потому, что вышла новая версия, и она «лучше». Т.е. начинается новый проект, ставишь свежую версию, работаешь — при этом все как было, потому что все устраивает. Что вам нужно от инструмента сборки? Чтобы работал.

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

        Ощущаете разницу в подходах?


      1. fzn7
        20.08.2021 11:29

        Кастомные плагины "под инфраструктуру". Гибкая система зависимостей, зависимость от проекта, scm, любого файла, варианта одного и того-же артефакта. Ускорение сборки в 5 раз за счет инкрементальной конфигурации, демонов и кэшей. Наконец Gradle не ограничен Java стеком - он поддерживает и гибко формирует граф зависимостей (с параллельной сборкой!) между всем чем угодно. Сборка, тест и деплой 18 разных вариантов одного Android приложения одной кнопкой с грэдлом это рядовое. С мавеном это даже не подходи