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

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

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

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

В частности:

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

Мои вопросы:

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

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

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

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

Чтобы узнать, в каком ключевом псевдониме есть закрытый ключ, используйте keytool -list -keystore store.jks (здесь я предполагаю тип магазина keytool -list -keystore store.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 

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

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

  • Как разрешены имена серверов сертификатов SSL / Можно ли добавлять альтернативные имена с помощью keytool?
  • Как легко создать сертификат SSL и настроить его в Apache2 в Mac OS X?
  • Как использовать ssh / scp между непубличными машинами
  • Динамические изображения, переданные через HTTPS, отображают сломанное изображение в слове при открытии HTTP-документа
  • Chrome говорит: «Эта страница содержит некоторые ресурсы, которые не защищены» на всех https-сайтах
  • Как отправить электронную почту через SSL SMTP с помощью .NET Framework?
  • Как вы подписываете запрос на подпись сертификата в своем сертификационном центре?
  • Как подключиться к защищенному сайту с использованием SSL в Java с файлом pkcs12?
  • Как сделать Java 6, которая не работает с SSL-соединением с неправильным отключением SSL-партнера, как Java 7?
  • javax.net.ssl.SSLException: Получено фатальное предупреждение: protocol_version
  • Как указать список шифров SSL / TLS, предлагаемый конкретным сайтом?
  • Давайте будем гением компьютера.