Рукопожатие могло произойти по разным причинам:
- Несовместимые наборы шифров, используемые клиентом и сервером. Это потребует от клиента использования (или включения) набора шифров, который поддерживается сервером.
- Используются несовместимые версии SSL (сервер может принимать только TLS v1, в то время как клиент может использовать только SSL v3). Опять же, клиент может убедиться, что он использует совместимую версию протокола SSL / TLS.
- Неполный путь доверия для сертификата сервера; сертификат сервера, вероятно, не является доверенным клиентом. Это обычно приводит к более подробной ошибке, но это вполне возможно. Обычно исправление заключается в импорте сертификата CA сервера в хранилище доверенных сертификатов клиента.
- Сертификат выдан для другого домена. Опять же, это привело бы к более подробному сообщению, но я изложу здесь исправление в случае, если это является причиной. Решением в этом случае было бы заставить сервер (он не кажется вашим) использовать правильный сертификат.
Так как основной сбой не может быть точно определен, лучше включить -Djavax.net.debug=all
флаг, чтобы разрешить отладку установленного соединения SSL. С включенной отладкой вы можете определить, какая активность в рукопожатии не удалась.
Обновить
Судя по имеющимся подробностям, похоже, что проблема связана с неполным путем доверия сертификата между сертификатом, выданным серверу, и корневым центром сертификации. В большинстве случаев это происходит из-за того, что сертификат корневого ЦС отсутствует в хранилище доверенных сертификатов, что приводит к ситуации, когда путь доверия сертификату не может существовать; сертификат по существу не доверен клиенту. Браузеры могут выдавать предупреждение, чтобы пользователи могли игнорировать это, но то же самое не относится к клиентам SSL (таким как класс HttpsURLConnection или любой клиентской библиотеке HTTP, такой как клиент Apache HttpComponents ).
Большинство этих клиентских классов / библиотек полагались бы на хранилище доверия, используемое JVM для проверки сертификата. В большинстве случаев это будет cacerts
файл в каталоге JRE_HOME / lib / security. Если местоположение хранилища доверенных сертификатов указано с помощью системного свойства JVM javax.net.ssl.trustStore
, то хранилище по этому пути обычно является хранилищем, используемым клиентской библиотекой. Если вы сомневаетесь, взгляните на свой Merchant
класс и выясните, какой класс / библиотеку он использует для установления соединения.
Добавление сертификата сервера, выдающего CA, в это хранилище доверия должно решить проблему. Вы можете обратиться к моему ответу на связанный вопрос о получении инструментов для этой цели, но для этой цели достаточно утилиты Java keytool .
Предупреждение. Хранилище доверенных сертификатов - это список всех доверенных центров сертификации. Если вы вставите сертификат, который не принадлежит ЦС, которому вы не доверяете, то соединения SSL / TLS с сайтами, имеющими сертификаты, выданные этим объектом, могут быть расшифрованы, если доступен закрытый ключ.
Обновление № 2: Понимание вывода трассировки JSSE
Склад ключей и хранилища доверенных сертификатов, используемые JVM, обычно перечислены в самом начале, примерно так:
keyStore is :
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: C:\Java\jdk1.6.0_21\jre\lib\security\cacerts
trustStore type is : jks
trustStore provider is :
Если используется неправильное хранилище доверенных сертификатов, вам необходимо повторно импортировать сертификат сервера в правильный или перенастроить сервер для использования указанного в списке (не рекомендуется, если у вас несколько JVM, и все они используются для разных необходимо).
Если вы хотите проверить, содержит ли список доверенных сертификатов требуемые сертификаты, существует раздел для него, который начинается с:
adding as trusted cert:
Subject: CN=blah, O=blah, C=blah
Issuer: CN=biggerblah, O=biggerblah, C=biggerblah
Algorithm: RSA; Serial number: yadda
Valid from SomeDate until SomeDate
Вам нужно будет искать, является ли ЦС сервера субъектом.
Процесс рукопожатия будет иметь несколько заметных записей (вам нужно знать SSL, чтобы понять их подробно, но для отладки текущей проблемы достаточно знать, что handshake_failure обычно сообщается в ServerHello.
1. ClientHello
О серии записей будет сообщено при инициализации соединения. Первое сообщение, отправленное клиентом в настройке соединения SSL / TLS, - это сообщение ClientHello, которое обычно регистрируется в журналах как:
*** ClientHello, TLSv1
RandomCookie: GMT: 1291302508 bytes = { some byte array }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA]
Compression Methods: { 0 }
***
Обратите внимание на используемые комплекты шифров. Это , возможно , придется согласиться с записью в файле merchant.properties, по той же конвенции могут быть использованы библиотекой банка. Если используется другое соглашение, нет причин для беспокойства, так как ServerHello сообщит об этом, если набор шифров несовместим.
2. ServerHello
Сервер отвечает ServerHello, который будет указывать, можно ли продолжить установку соединения. Записи в журналах обычно бывают следующего типа:
*** ServerHello, TLSv1
RandomCookie: GMT: 1291302499 bytes = { some byte array}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
***
Обратите внимание на набор шифров, который он выбрал; это лучший набор, доступный как для сервера, так и для клиента. Обычно набор шифров не указывается в случае ошибки. Сертификат сервера (и, необязательно, всей цепочки) отправляется сервером и может быть найден в записях как:
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=server, O=server's org, L=server's location, ST =Server's state, C=Server's country
Signature Algorithm: SHA1withRSA, OID = some identifer
.... the rest of the certificate
***
Если проверка сертификата прошла успешно, вы найдете запись, похожую на:
Found trusted certificate:
[
[
Version: V1
Subject: OU=Server's CA, O="Server's CA's company name", C=CA's country
Signature Algorithm: SHA1withRSA, OID = some identifier
Один из описанных выше шагов не был бы успешным, что привело бы к handshake_failure, поскольку рукопожатие обычно завершается на этом этапе (не совсем, но последующие этапы рукопожатия обычно не вызывают сбой рукопожатия). Вам необходимо выяснить, на каком этапе произошел сбой, и опубликовать соответствующее сообщение в качестве обновления вопроса (если вы уже не поняли сообщение и не знаете, что делать, чтобы его решить).