Image

Imagekolemik wrote in Imageru_java

Category:

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).
  1. Переводим ключи и сертификаты в 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
  2. Так как 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
  3. Теперь скачиваем сумер мега класс ImportKey и ещё раз (компиленный класс, ещё раз).
  4. Запускаем его:
    java ImportKey custom_key.der custom_cert.der
  5. В результате обретаем файл ~/keystore.ImportKey, который и есть требуемая JKS.
  6. Скопируем этот файл как custom.jks в корневую папочку вашего проекта. Пароль к такому хранилищу задан как "importkey".

Теперь перед попыткой соединения надо лишь установить системные свойства:
System.setProperty("javax.net.ssl.keyStore", "custom.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "importkey");
 
Если у вас так же косячный HTTPS сервер, то придётся ещё немного попотеть и добавить данный сертификат в "доверенные".
  1. Заходим на любой урл нашего сервера через обычный браузер (FireFox).
  2. Видим сообщения про риски.
  3. Просматриваем сертификат и сохраняем его локально в формате DER.
  4. Выполняем команду (попросят ввести пароль - вводим какой-нибудь простой, типа "qwerty"):
    keytool -importcert -trustcacerts -file my_server_cert.der -keystore trust_certs -v -alias my_server
  5. Выставляем системные свойства:
    System.setProperty("javax.net.ssl.trustStore", "trust_certs");
    System.setProperty("javax.net.ssl.trustStorePassword", "qwerty"); // "qwerty" - это пароль, введённый нами при создании хранилища доверенных сертификатов на предыдущем шаге

Вот тут интересность... Оказывается, что JKS хранилища имеют пароль только на запись (по-умолчанию). Поэтому, несмотря на то, что в пункте 4 вы вводили какой-то свой пароль, в системных свойствах ничего указывать не надо. Можете проверить доступность вашего сертификата той же утилитой keytool:
keytool -v -list -keystore trust_certs



То же самое, но в моём дневничке можно почитать тут.