почему java не отправляет сертификат клиента во время рукопожатия SSL? - PullRequest
60 голосов
/ 15 февраля 2012

Я пытаюсь подключиться к безопасному веб-сервису.

Я получил сбой при рукопожатии, хотя мои хранилище ключей и доверенные хранилища были установлены правильно.

После нескольких дней разочарований, бесконечныхпогуглив и спросив всех вокруг, я обнаружил, что единственная проблема заключалась в том, что java решил не отправлять сертификат клиента на сервер во время рукопожатия.

В частности:

  1. Сервер запросил клиентасертификат (CN = RootCA) - то есть «дайте мне сертификат, подписанный корневым центром сертификации»
  2. Java просмотрел хранилище ключей и обнаружил только мой сертификат клиента, подписанный «SubCA», который, в свою очередь,выдается "RootCA".Это не удосужилось заглянуть в склад доверенных сертификатов ... да ладно, я думаю
  3. К сожалению, когда я попытался добавить сертификат "SubCA" в хранилище ключей, это не помогло вообще.Я проверил, загружены ли сертификаты в хранилище ключей.Они делают, но KeyManager игнорирует все сертификаты, кроме клиентского.
  4. Все вышеперечисленное приводит к тому, что java решает, что у него нет сертификатов, которые удовлетворяют запросу сервера, и ничего не отправляет ... tadaaaсбой рукопожатия: - (

Мои вопросы:

  1. Возможно ли, что я добавил сертификат "SubCA" в хранилище ключей таким образом, что "разорвал цепочку сертификатов"или что-то так, что KeyManager загружает только сертификат клиента и игнорирует остальные? (Chrome и openssl удается выяснить это, так почему не может Java? - обратите внимание, что сертификат "SubCA" всегда представляется отдельно как доверенный орган, так что Chromeпо-видимому, правильно упаковывает его вместе с клиентским сертификатом во время рукопожатия)
  2. Является ли это формальной «проблемой конфигурации» на стороне сервера? Сервер является третьей стороной. Я ожидаю, что сервер запросит сертификат, подписанныйПолномочия "SubCA", так как это то, что они нам предоставили. Я подозреваю, что фактчто это работает в Chrome и openssl, потому что они "менее строгие", а java просто идет "по книге" и терпит неудачу.

Мне удалось собрать грязный обходной путь для этого, но яЯ не очень рад этому, поэтому я буду рад, если кто-нибудь сможет уточнить это для меня.

Ответы [ 3 ]

89 голосов
/ 16 февраля 2012

Возможно, вы импортировали промежуточный сертификат CA в хранилище ключей, не связывая его с записью, в которой у вас есть сертификат клиента и его закрытый ключ.Вы должны увидеть это, используя keytool -v -list -keystore store.jks.Если вы получаете только один сертификат для каждой записи псевдонима, они не вместе.

Вам необходимо импортировать сертификат и его цепочку вместе в псевдоним хранилища ключей, в котором есть ваш закрытый ключ.

Комучтобы узнать, какой псевдоним хранилища ключей имеет закрытый ключ, используйте keytool -list -keystore store.jks (здесь я предполагаю тип хранилища JKS).Это скажет вам что-то вроде этого:

Your keystore contains 1 entry

myalias, Feb 15, 2012, PrivateKeyEntry, 
Certificate fingerprint (MD5): xxxxxxxx

Здесь псевдоним myalias.Если вы используете -v в дополнение к этому, вы должны увидеть Alias Name: myalias.

Если у вас его еще нет отдельно, экспортируйте свой сертификат клиента из хранилища ключей:

keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias

Это должно дать вам файл PEM.

Используя текстовый редактор (или cat), подготовьте файл (назовем его bundle.pem) с этим клиентским сертификатом и промежуточным сертификатом CA (и, возможно, корневым).Сам сертификат CA, если хотите), так что сертификат клиента находится в начале, а его сертификат эмитента чуть ниже.

Это должно выглядеть следующим образом:

-----BEGIN CERTIFICATE-----
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
....
-----END CERTIFICATE-----

Теперь импортируйте этосвязать вместе в псевдоним, где ваш закрытый ключ:

keytool -importcert -keystore store.jks -alias myalias -file bundle.pem
5 голосов
/ 23 июля 2014

В качестве дополнения вы можете использовать %> openssl s_client -connect host.example.com:443, посмотреть дамп и проверить, что все основные сертификаты действительны для клиента.Вы ищете это в нижней части вывода. Проверьте код возврата: 0 (нормально)

Если вы добавите -showcerts , он выведет всю информацию о связке ключей, которая была отправлена ​​вместе с сертификатом хоста, которыйэто то, что вы загрузили в свою связку ключей.

0 голосов
/ 06 февраля 2019

Дело в том, что при использовании клиентского сертификата, подписанного промежуточным сертификатом, необходимо включить промежуточный сертификат в свой список пользователей, чтобы java мог его найти.Либо в одиночку, либо в виде связки с корнем, выдающим приблизительно.

...