Ошибка установления связи Java SSL - нет сертификата клиента

Я использую стороннюю библиотеку со встроенным ssl-клиентом для выполнения проверки CRL для подписи PKCS # 7.

Я создал хранилище ключей и хранилище доверенных сертификатов и поместил центр сертификации сервера в свое хранилище доверенных сертификатов.

Если посмотреть на отладку ниже, центры сертификации и цепочка сертификатов пусты. Мой клиент не отправил обратно свой сертификат.

Не могли бы вы объяснить, что происходит?

РЕДАКТИРОВАТЬ

Благодаря комментариям ниже я понял, что «пустой ЦС» клиента не проблема.

Проблема в том, что сервер запрашивает сертификат клиента, но мой клиент не отправляет его на сервер.

Почему клиент не отправляет свой сертификат?

keyStore is : [...]
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
***
found key for : [...]
chain [0] = [
...
]
***
trustStore is: [...]
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
[...]

trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[...]
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(10000) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1445266954 bytes = { 44, 84, 229, 125, 84, 33, 145, 120, 170, 228, 77, 65, 146, 200, 227, 227, 48, 200, 116, 240, 140, 55, 227, 162, 119, 75, 116, 47 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [host_name: ...]
***
[write] MD5 and SHA1 hashes:  len = 176
[...]
main, WRITE: TLSv1 Handshake, length = 176
[Raw write]: length = 181
[...]
[Raw read]: length = 5
[...]
[Raw read]: length = 85
[...]
main, READ: TLSv1 Handshake, length = 85
*** ServerHello, TLSv1
RandomCookie:  GMT: 1929314415 bytes = { 133, 174, 213, 209, 239, 104, 185, 151, 182, 150, 87, 234, 171, 201, 244, 45, 171, 118, 159, 20, 148, 138, 19, 5, 1, 44, 188, 76 }
Session ID:  {144, 227, 198, 123, 46, 241, 49, 85, 156, 181, 102, 130, 42, 23, 39, 17, 11, 64, 23, 39, 166, 11, 119, 139, 12, 51, 60, 252, 170, 105, 23, 161}
Cipher Suite: SSL_RSA_WITH_3DES_EDE_CBC_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
Extension server_name, server_name: 
***
%% Initialized:  [Session-1, SSL_RSA_WITH_3DES_EDE_CBC_SHA]
** SSL_RSA_WITH_3DES_EDE_CBC_SHA
[read] MD5 and SHA1 hashes:  len = 85
[...]
[Raw read]: length = 5
[...]
[Raw read]: length = 1024
[...]
main, READ: TLSv1 Handshake, length = 1024
*** Certificate chain
chain [0] = [
[
 [...]
]
  Algorithm: [SHA1withRSA]
  Signature:
[...]

]
***
Found trusted certificate:
[
[...]
]
[read] MD5 and SHA1 hashes:  len = 1024
[...]
[Raw read]: length = 5
[...]
[Raw read]: length = 8
[...]
main, READ: TLSv1 Handshake, length = 8
*** CertificateRequest
Cert Types: RSA
Cert Authorities:
<Empty>
[read] MD5 and SHA1 hashes:  len = 8
[...]
[Raw read]: length = 5
[...]
[Raw read]: length = 4
[...]
main, READ: TLSv1 Handshake, length = 4
*** ServerHelloDone
[read] MD5 and SHA1 hashes:  len = 4
[...]
*** Certificate chain
***
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
[write] MD5 and SHA1 hashes:  len = 269
[...]
main, WRITE: TLSv1 Handshake, length = 269
[Raw write]: length = 274
[...]
SESSION KEYGEN:
PreMaster Secret:
[...]
CONNECTION KEYGEN:
Client Nonce:
[...]
Server Nonce:
[...]
Master Secret:
[...]
Client MAC write Secret:
[...]
Server MAC write Secret:
[...]
Client write key:
[...]
Server write key:
[...]
Client write IV:
[...]
Server write IV:
[...]
main, WRITE: TLSv1 Change Cipher Spec, length = 1
[Raw write]: length = 6
[...]
*** Finished
verify_data:  { 212, 27, 4, 13, 87, 128, 70, 120, 43, 97, 111, 135 }
***
[write] MD5 and SHA1 hashes:  len = 16
[...]
Padded plaintext before ENCRYPTION:  len = 40
[...]
main, WRITE: TLSv1 Handshake, length = 40
[Raw write]: length = 45
[...]
[Raw read]: length = 5
[...]
[Raw read]: length = 2
[...]
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, handshake_failure
%% Invalidated:  [Session-1, SSL_RSA_WITH_3DES_EDE_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

person jBravo    schedule 19.10.2015    source источник
comment
Я удивлен, что что-то при проверке CRL (на PKCS # 7 или на чем-то еще) устанавливает какое-либо соединение SSL / TLS. Лучшая практика для получения CRL, а также OCSP - использовать простой HTTP или что-то еще, например, LDAP, чтобы избежать бесконечных циклов. данные (тело CRL или OCSP) уже подписаны и не нуждаются в дополнительной целостности или обычно в какой-либо конфиденциальности.   -  person dave_thompson_085    schedule 20.10.2015
comment
Есть ли что-нибудь в сообщении Certificate chain после ServerHelloDone (не уверен, удалили ли вы какие-то строки).   -  person Bruno    schedule 21.10.2015
comment
Цепочка сертификатов пуста.   -  person jBravo    schedule 21.10.2015
comment
Какой тип ключа для сертификата в вашем хранилище ключей? (Я предполагаю из вашего сокращенного вывода вверху, что действительно существует хранилище ключей, которое содержит сертификат с соответствующим закрытым ключом)   -  person Bruno    schedule 21.10.2015


Ответы (4)


Мне не хватало того факта, что сертификат клиента должен быть сгенерирован сервером с помощью запроса на подпись сертификата (CSR).

Процесс такой:

  1. Создайте пару ключей (через keytool -genkey)
  2. Создайте CSR PKCS # 10 (с помощью keytool -certreq)
  3. Отправьте CSR в соответствующий орган
  4. Вернуть сертификат SSL

Спасибо за комментарии, которые помогли мне улучшить понимание SSL.

person jBravo    schedule 21.10.2015

Если клиент не отправляет сертификат, это означает 2 вещи: 1. Сервер не запросил сертификат (поэтому нет CertificateRequest) 2. Сервер запросил сертификат, но ваше хранилище ключей не запросило сертификат.

person maddy10    schedule 23.12.2016

Просто хотел бросить на это свои 2 цента. Я видел именно эту ошибку в журнале консоли. После долгих поисков и проб я наконец понял, в чем была ошибка. Пароль для моего хранилища ключей был неверным. Эта ошибка никогда не отображалась в журналах, она просто выдала ошибку и вызвала множество ошибок ssl.

person Robert Cadmire    schedule 03.04.2019

центры сертификации и цепочка сертификатов пусты.

Это означает, что в хранилище доверенных сертификатов сервера нет доверенных сертификатов ЦС.

Мой клиент не вернул свой сертификат.

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

person user207421    schedule 19.10.2015
comment
Но если сервер никому не доверяет, могу ли я установить SSL-соединение? Это моя проблема? - person jBravo; 20.10.2015
comment
Я отредактировал свой пост, чтобы исправить свою терминологическую ошибку. Простите за это. - person jBravo; 20.10.2015
comment
Если сервер никому не доверяет, никто не сможет пройти аутентификацию через сертификат клиента. Тем не менее, ваш сервер запрашивает один и прерывает соединение, когда он его не получает. Вам просто нужно решить, нужен ли вам сертификат клиента или нет, и если да, то каким эмитентам вы будете доверять. - person user207421; 20.10.2015
comment
Пустой список CAlist не обязательно ничего говорит о хранилище доверенных сертификатов сервера; tools.ietf.org/html/rfc5246#section-7.4.4 позволяет серверу отправлять пустой список, а клиенту - любой сертификат, который он хочет, а в моем тестирующем клиенте JSSE с установленным по умолчанию SunX509KeyManagerImpl отправляет первый найденный для любого запрошенного типа (алгоритма). Я не знаю ни одного стека, который запрашивает только тип RSA, как показано здесь, но если я тестирую с OpenSSL ‹1.0.0, который не запрашивает тип ECDSA, а мой единственный ключ - EC (DSA), JSSE не отправляет сертификат (пустой сообщение client-Cert). Журнал показывает, что один ключ загружен, но детали опущены; наверное это не RSA. - person dave_thompson_085; 20.10.2015
comment
Браузеры, которые я использую (IE, FF, Chrome), если сервер отправляет пустой список CAlist, все предлагают пользователю выбрать закрытый ключ, если он существует. Очевидно, что если пользователь или такой код, как JSSE, выбирает / угадывает сертификат, которому сервер не доверяет, это очень плохо, поэтому лучше, если сервер действительно отправляет CAlist того, что он действительно хочет, но не требуется. - person dave_thompson_085; 20.10.2015
comment
Итак, сервер попросил моего клиента отправить сертификат без точной информации о ЦС, которому он доверяет. Мой клиент ничего не отправил, поэтому сервер вернул предупреждение handshake_failure. Это оно? - person jBravo; 20.10.2015