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