SSL, Java, форматы сертификатов

16.05.2008
Последняя модификация:14.05.2011
Иванов Аркадий

 

Java любит работать с хранилищами сертификатов типа JKS. Иногда приходится импортировать в JKS сертификаты другого формата. И наоборот.

 
 
Совершенно обычная задача: PEM =====> JKS
- есть хост, с которым устанавливается SSL соединение из программы на Java.
- на этом хосте есть самоподписанный сертификат.
- для того, чтобы соединение было возможно, следует сертификат этого хоста вставить в хранилище доверяемых сертификатов (trustedcerts) на нашей машине.
- сертификаты для почты, для WEB-сервера уже есть на этом хосте, они подготовлены пакетом openssl и у них формат PEM.
- Необходимо импортировать имеющийся сертификат формата PEM в JKS.

Процедура:

Предположим, что у вас есть в PEM-фомате файл приватного ключа key.pem и файл сертификата cert.pem.
Обычно и сертификат и приватный ключ лежат в одном текстовом файле. Вы можете разделить их любым текстовым редактором и создать эти файлы.
Конвертируем оба в DER-формат c помощью команды openssl:

openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER

В результате получим файлы key.der и cert.der.

Для импортирования этих файлов в JKS хранилище служит программа ImportKey.java.
Скачайте java-исходник, скомпилируйте и запустите:

 

user@host:~$ java ImportKey key.der cert.der

 

Программа создаст хранилище: /home/user/keystore.ImportKey
Alias: importkey Password: importkey
Теперь вытащим из нового хранилища сертификат:

keystore -exportcert -file importkey.cer -alias importkey -keystore keystore.ImportKey

 

Получим файл importkey.cer.
Теперь можно импортировать сертификат в хранилище доверяемых сертификатов.
Это хранилище находится в файле $JAVA_HOME/jre/lib/security/cacerts.
Переходим в каталог с хранилищем, копируем туда файл сертификата и импортируем следующей командой:

keytool -import -trustcacerts -alias importkey -file importkey.cer -keystore cacerts


Если не хочется запихивать что-либо в cacerts, можно создать отдельное хранилище доверямых сертификатов и указать программе, что надо использовать именно его:
- Создаём собственное хранилище в домашнем каталоге (при создании будет запрошен пароль. Используем "changeit") :

 keytool -import -trustcacerts -alias importkey -file importkey.cer -keystore mytrusted

- Указываем программе с помощью System Properties использовать именно это хранилище:

System.setProperty("javax.net.ssl.trustStore", "/home/user/mytrusted");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

 
 

 

Ещё одна совершенно обычная задача:  JKS =====> PEM

- есть хост, на который надо установить PEM-сертификат. Например это хост с Апачей или Postfix, IMAP
- на этом хосте уже есть самоподписанный сертификат, например для Tomcat-а.
- сначала экспортируем ключ и сертификат в формат PKCS12:

keytool -importkeystore -srckeystore jksstore -destkeystore pkcs12store -srcstoretype JKS -deststoretype PKCS12 -srcstorepass changeit -deststorepass secret -srcalias myalias -destalias newalias -srckeypass changeit -destkeypass secret


получили новое хранилище pkcs12store.

- конвертируем из PKCS12 в PEM:

 openssl pkcs12 -in pkcs12store  -out pemstore -nodes

- дальше с этим pemstore то, что нам нравится.

ЗАМЕЧАНИЕ: при первоначальной генерации ключей в хранилище JKS стоит указывать -keyalg RSA. Я нарвался на то, что по умолчанию генерируются приватные ключи DSA и конвертируются естественно тоже в DSA. А вот uw-imap у меня отказался съесть DSA, ему подавай только RSA.

 

 

Конвертация ключей с помощью keytool от Java 6: JKS ==> P12 ==> PEM

 В этой версии keytool стал уметь многое. Вот последовательность команд, с помощью которой можно сгенерить ключи и получить все их формы:

 

Создание ключа и сертификата в JKS хранилище:
keytool -keystore my.jks -genkeypair -sigalg RSA -alias myalias  -dname 'CN=myhost.mydomain,L=mycity,ST=mystate,C=RU'
Экспорт в P12:
keytool -importkeystore -srckeystore my.jks -destkeystore my.p12  -srcstoretype jks  -deststoretype pkcs12
Экспорт в PEM:
openssl pkcs12 -in my.p12 -out my.pem
На всякий случай сниму пароль с ключа и получу секретный ключ без пароля:
openssl rsa -in my.pem -out mysecret.pem