Java + SSL(pkcs12) - небольшое HowTo
Хочу поделиться с обществом моим How-To по подсоединению через Java ко всяким HTTPS-секьюрным серверам. Итак, имеем:Java и SSL!
Не так то просто наладить взаимодействие этой сладкой парочки. В порыве гугления я обнаружил некоторые типовые рецепты работы:
http://www.agentbob.info/agentbob/79-AB.html
http://www.sslshopper.com/article-most-common-openssl-commands.html
Но соеденить их воедино достаточно проблематично, ибо не ясна логика.
Первым делом обозначу условия:Необходимо выполнить HTTP POST запрос на неком сервере, используя SSL (HTTPS). Для доступа к серверу выдаётся сертификат в формате PKCS12 (расширение p12 или xep). Кроме того сам протокол защищён сертификатом, который, как это принято, не подписан, не валиден и вообще.
Первым делом разбираемся с переводом нашего p12 сертификата в приемлимый для Java вид - JKS (Java Key Store).
- Переводим ключи и сертификаты в PEM формат:
openssl pkcs12 -in custom_cert.p12 -out custom_cert.pem -nodes -nokeys
openssl pkcs12 -in custom_cert.p12 -out custom_key.pem -nodes -nocerts - Так как Java ещё не понимает PEM, то даунгрейдим до DER:
openssl pkcs8 -topk8 -nocrypt -in custom_key.pem -inform PEM -out custom_key.der -outform DER
openssl x509 -in custom_cert.pem -inform PEM -out custom_cert.der -outform DER - Теперь скачиваем сумер мега класс ImportKey и ещё раз (компиленный класс, ещё раз).
- Запускаем его:
java ImportKey custom_key.der custom_cert.der - В результате обретаем файл ~/keystore.ImportKey, который и есть требуемая JKS.
- Скопируем этот файл как custom.jks в корневую папочку вашего проекта. Пароль к такому хранилищу задан как "importkey".
Теперь перед попыткой соединения надо лишь установить системные свойства:
System.setProperty("javax.net.ssl.keyStore", "custom.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "importkey");
Если у вас так же косячный HTTPS сервер, то придётся ещё немного попотеть и добавить данный сертификат в "доверенные".
- Заходим на любой урл нашего сервера через обычный браузер (FireFox).
- Видим сообщения про риски.
- Просматриваем сертификат и сохраняем его локально в формате DER.
- Выполняем команду (попросят ввести пароль - вводим какой-нибудь простой, типа "qwerty"):
keytool -importcert -trustcacerts -file my_server_cert.der -keystore trust_certs -v -alias my_server
- Выставляем системные свойства:
System.setProperty("javax.net.ssl.trustS
tore", "trust_certs");
System.setProperty("javax.net.ssl.trustStorePassword", "qwerty"); // "qwerty" - это пароль, введённый нами при создании хранилища доверенных сертификатов на предыдущем шаге
Вот тут интересность... Оказывается, что JKS хранилища имеют пароль только на запись (по-умолчанию). Поэтому, несмотря на то, что в пункте 4 вы вводили какой-то свой пароль, в системных свойствах ничего указывать не надо. Можете проверить доступность вашего сертификата той же утилитой keytool:
keytool -v -list -keystore trust_certs
То же самое, но в моём дневничке можно почитать тут.
