Подтвердить что ты не робот

Почему Java не отправляет сертификат клиента во время подтверждения SSL?

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

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

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

В частности:

  • Сервер запросил сертификат клиента (CN = RootCA) - то есть "дайте мне сертификат, подписанный корневым ЦС"
  • Java заглянула в хранилище ключей и только нашла мой клиентский сертификат, подписанный "SubCA", который, в свою очередь, выдается "RootCA". Он не потрудился заглянуть в доверительную сеть... duh OK Я думаю,
  • К сожалению, когда я попытался добавить сертификат "SubCA" в хранилище ключей, это совсем не помогло. Я проверил, загружены ли сертификаты в хранилище ключей. Они делают, но KeyManager игнорирует все сертификаты, кроме клиентского.
  • Все вышеизложенное приводит к тому, что java решает, что у него нет сертификатов, удовлетворяющих запросу сервера, и ничего не посылает... tadaaa handshake failure: - (

Мои вопросы:

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

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

4b9b3361

Ответ 1

Возможно, вы могли импортировать промежуточный сертификат 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) с этим сертификатом клиента и промежуточным сертификатом ЦС (и, возможно, самим сертификатом корневого ЦС, если хотите), чтобы клиент -сертификат находится в начале, и его сертификат эмитента находится чуть ниже.

Это должно выглядеть так:

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

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

keytool -importcert -keystore store.jks -alias myalias -file bundle.pem

Ответ 2

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

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

Ответ 3

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