Pull to refresh

Особенности работы с SSL сертификатами в Java

Возникла задача — обеспечить работу java программы в качестве клиента по протоколу ssl.
Программой был Apache Tomcat но изложенный материал можно применить к любой java программе.
Не смотря на то, что до этого имелся опыт по настройке SSL в java, с необходимостью использовать уже сгенерированный приватный ключ и подписанный клиентский сертификат, столкнулся впервые. Пытаясь решить поставленную задачу наступил на пару граблей. Тому как этого избежать и посвящен данный пост.

Описание задачи



Есть web приложение размещенное под Tomcat. Сам Tomcat «стоит» за Apache подключенный посредством модуля mod_jk. В процессе подключения приложения к платежной системе возникла необходимость обеспечить доступность данного приложения по протоколу ssl. Нами был сгенерирован приватный клиентский ключ (сert.key), отправлен запрос на получения сертификата и получен сам сертификат (сert.crt) и корневой сертификат (ca.crt). С настройкой ssl на Apache проблем не возникло, в сети полно примеров. Так как Tomcat подключен к Apache по AJP протоколу, никаких дополнительных настроек Tomcat не потребовалось. Всё заработало.

Далее, приложению потребовалось обратиться к web сервису платежной системы. Протокол естественно ssl но в добавок ещё авторизация клиента через выданный клиентский сертификат. В итоге на наш вызов web сервиса получаем

HTTP/1.0 403 Client certificate required

На этом этапе вспоминаем как работать в java с ssl и добавляем в строку запуска Tomcat
(если быть точнее в переменную JAVA_OPTS, но это не суть важно) параметры

-Djavax.net.ssl.trustStore=trust.ks
-Djavax.net.ssl.trustStorePassword=123456
-Djavax.net.ssl.keyStore=key.ks
-Djavax.net.ssl.keyStorePassword=123456


В trust.ks (trustStore) необходимо разместить корневой сертификат, в key.ks (keyStore) соответственно клиентский.

Размещаем корневой сертификат:

keytool -keystore server.ks -storepass 123456 -import -file ca.crt

Теперь очередь за клиентским. И вот тут грабли раз — как разместить сert.key и cert.crt в key.ks?

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

  1. Объединяем содержимое файлов cert.key и cert.crt в один и называем его например сert.pem
  2. Качаем программу Portecle (http://portecle.sourceforge.net) GUI программа для работы с хранилищем сертификатов java
  3. Открываем программой наш key.ks, потом Tools->Import Key Pair и выбираем cert.pem
  4. Далее программа попросит указать пароль для импортируемой «Ключевой Пары». И здесь меня поджидали вторые грабли. Пароль для «Ключевой Пары» ДОЛЖЕН СОВПАДАТЬ с паролем хранилища. В нашем случае это 123456.


После чего всё заработало.

Небольшие комментарии



  • не указывать пароль для хранилища ключей нельзя. В этом случае возникает ошибка java.security.UnrecoverableKeyException: Password must not be null
  • при несоответствии паролей хранилища и «Ключевой Пары» возникает ошибка java.security.UnrecoverableKeyException: Cannot recover key
  • пароль «Ключевой Пары» это фактически пароль для дополнительной защиты приватного клиентского ключа (cert.key), его может в файле и не быть. В моём случае приватный клиентский ключ был первоначально сгененрирован openSSH как раз без пароля
  • я так и не смог импортировать «Ключевую Пару» в хранилище с помощью программы keytool, если кто знает как это сделать пожалуйста поделитесь
  • статья о различных сценариях использования SSL сертификатов сервером и клиентом (на английском) http://community.jboss.org/wiki/sslsetup
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.