Featured image of post Генерация сертификатов и хранилища ключей Java

Генерация сертификатов и хранилища ключей Java

Создание сертификатов для Java приложений

В Java-приложениях для обеспечения безопасности данных и установления защищённых соединений (например, HTTPS) используется специальное хранилище — keystore. Оно предназначено для хранения секретной информации, такой как закрытые ключи и сертификаты.

Существуют различные форматы хранилищ, поддерживаемые Java:

JKS (Java KeyStore) — традиционный формат, использующийся по умолчанию. Представляет собой файл с расширением .jks и применяется чаще всего.
JCEKS — расширенная версия JKS, в которой реализовано более надёжное шифрование (Triple DES). При необходимости можно преобразовать JKS-хранилище в JCEKS с помощью команды утилиты keytool.
PKCS12 — формат, ориентированный на перенос и хранение пользовательских закрытых ключей и сертификатов. Часто используется для взаимодействия с внешними системами.

Каждая запись в keystore идентифицируется с помощью уникального имени — alias. В целях надёжности рекомендуется избегать alias’ов, отличающихся только регистром символов.
Безопасность данных в хранилище обеспечивается двойным способом: каждое ключевое значение может быть защищено индивидуальным паролем, а всё хранилище — отдельным общим паролем.

Вся информация в keystore делится на два типа:
Ключевые записи — пары закрытого и открытого ключей (private/public).
Доверенные сертификаты — сертификаты центров сертификации и других доверенных источников.

Для управления содержимым keystore Java предоставляет встроенную утилиту keytool, находящуюся в каталоге bin установки JDK. С её помощью можно создавать, просматривать, изменять и удалять ключи и сертификаты.

Как правило создаются keystore и truststore. Keystore - содержит личный ключ + сертификат (цепочку сертификатов) сервера, а truststore сертификат ЦА (root-ca).

Создание хранилища и добавление самоподписанного сертификата

Генерация самоподписанного сертификата и запись его в хранилище:

1
2
3
4
5
6
7
8
9
keytool -genkeypair \
  -alias mykey \
  -keyalg RSA \
  -keysize 2048 \
  -validity 365 \
  -keystore keystore.jks \
  -storepass your_password \
  -keypass your_password \
  -dname "CN=myhost, OU=Company, O=MyCompany, L=City, ST=MyState, C=RU"

-alias — имя ключа.
-keystore — файл keystore’а (если не существует — будет создан).
-storepass, -keypass — пароли хранилища и ключа.
-validity — срок действия (в днях).
-dname — информация о владельце (DN).

Конвертация JKS хранилища в PKCS12:

Более современный формат

1
2
3
4
keytool -importkeystore \
  -srckeystore ./mycerts/keystore.jks \
  -destkeystore ./mycerts/keystore.p12 \
  -deststoretype PKCS12

Добавление сертификата ЦА в truststore:

1
2
3
4
5
keytool -importcert \
  -alias rootca \
  -file root-ca.cer \
  -keystore truststore.jks \
  -storepass your_password

Экспорт сертификата ЦА из хранилища:

1
2
3
4
5
keytool -exportcert \
  -alias rootca \
  -keystore truststore.jks \
  -file root-ca.cer \
  -storepass your_password

Просмотр содержимого сертификата:

1
keytool -printcert -file myserver.cer

Генерация SSL сертификата для JAVA в проде (ЦА):

Создать cnf

Конфиг файл для выпуска CSR

1
sudo nano cert.cnf

C cодержимым:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[req]
default_bits       = 2048
prompt             = no
default_md         = sha256
req_extensions     = req_extensions
distinguished_name = dn

[dn]
C  = RU
ST = Moscow
L  = Moscow
O  = Company
OU = IT
CN = myserver.domain.local

[req_extensions]
subjectAltName   = @alter_name
extendedKeyUsage = clientAuth
basicConstraints = CA:FALSE
keyUsage         = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment

[alter_name]
DNS.1 = myserver.domain.local
IP.1  = 192.168.1.100

Выпустить приватный ключ

Он же будет использоваться для сертификата:

1
openssl genrsa -out certkey.key 2048

Выпустить CSR

1
openssl req -new -key certkey.key -out cert.csr -config cert.cnf

Выпускаем сертификат с ЦА
Полученный сертификат можно использовать вместе с выпущенным ранее ключом

Для авторизации сервисов в Java приложении нужно использовать корневой сертификат + выпущенный сертификат и ключ.
Если при выпуске приватного ключа был указан пароль, также нужно будет указать пароль.

Выпустить pkcs12

password - указать новый пароль, который будет использоваться в дальнейшем:

1
2
3
4
5
6
7
8
openssl pkcs12 -export \
  -in cert.crt \
  -inkey certkey.key \
  -out cert.p12 \
  -name cert \
  -CAfile ca.crt \
  -caname root \
  -passout pass:password

Выпустить keystore

1
2
3
4
5
6
7
8
keytool -importkeystore \
  -deststorepass password \
  -destkeypass password \
  -destkeystore cert.keystore.jks \
  -srckeystore cert.p12 \
  -srcstoretype PKCS12 \
  -srcstorepass password \
  -alias cert

Выпустить truststore

1
2
3
4
5
6
keytool -keystore cert.truststore.jks \
  -alias CARoot \
  -importcert \
  -file ca.crt \
  -storepass password \
  -noprompt
Информацию можно использовать в свободном доступе, с указанием ссылки на сайт
Telegram GitHub