Java 版本“1.7.0_79”的 SSL 握手失败

Posted

技术标签:

【中文标题】Java 版本“1.7.0_79”的 SSL 握手失败【英文标题】:SSL Handshake failure with Java version "1.7.0_79" 【发布时间】:2017-03-10 13:44:25 【问题描述】:

我正在使用 Apache HttpClient 与 Java 中的主机之一通信,它正在抛出 handshake_failure。完整的跟踪是

触发 SecureRandom 播种完成播种 SecureRandom Ignoring 不可用的密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 忽略 不可用的密码套件:TLS_DHE_RSA_WITH_AES_256_CBC_SHA 忽略 不可用的密码套件:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 忽略 不支持的密码套件:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 忽略 不支持的密码套件:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 忽略 不支持的密码套件:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 忽略 不支持的密码套件:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 忽略不支持的密码套件:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 忽略不受支持的密码套件: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 忽略不支持的密码 套件:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 忽略不支持 密码套件:TLS_RSA_WITH_AES_256_CBC_SHA256 忽略不可用 密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 忽略 不支持的密码套件:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 忽略不受支持的密码套件: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 忽略不可用的密码 套件:TLS_DHE_DSS_WITH_AES_256_CBC_SHA 忽略不支持的密码 套件:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 忽略不支持 密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 忽略 不支持的密码套件:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 忽略不可用的密码套件:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 忽略不可用的密码套件:TLS_RSA_WITH_AES_256_CBC_SHA 忽略不支持的密码套件:TLS_RSA_WITH_AES_128_CBC_SHA256 允许不安全的重新协商:false 允许遗留的 hello 消息:true 是 初始握手:true 是否安全重新协商:false %% 无缓存 客户会话 * ClientHello, TLSv1 RandomCookie: GMT: 1477593324 bytes = 140, 171, 214, 217, 33, 165, 60, 228, 102, 207, 88, 112, 29, 40, 198, 242, 159, 61, 172, 89, 116, 98, 7, 195, 182, 144, 159, 226 会话 ID: 密码套件:[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] 压缩方法:0扩展elliptic_curves,曲线名称: 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 扩展 ec_point_formats,格式:[未压缩] 扩展 server_name, server_name: [host_name: integration.swiggy.com] [写入] MD5 和 SHA1 哈希:len = 180 0000: 01 00 00 B0 03 01 58 12 49 EC 8C AB D6 D9 21 A5 ......XI... .!. 0010: 3C E4 66 CF 58 70 1D 28 C6 F2 9F 3D AC 59 74 62 <.f.xp. c3 b6 e2 c0 .... ....3.2......... ...... ff ................ ........ tegration.swiggy> .com 主要,写入:TLSv1 握手,长度 = 180 [原始写入]:长度 = 185 0000:16 03 01 00 B4 01 00 00 B0 03 01 58 12 49 EC 8C ......X.I.. 0010:AB D6 D9 21 A5 3C E4 66 CF 58 70 1D 28 C6 F2 9F ...!.<.f.xp. ac c3 b6 e2 c0 ... ...... ff .2........> 00 12 00 04 00 05 00 14 ...... 0090: 00 08 00 16 00 0B 00 02 01 00 00 00 00 1B 00 19 ...... 00A0: 00 00 16 69 6E 74 65 67 72 61 74 69 6F 6E 2E 73 ...集成.s 00B0:77 69 67 67 79 2E 63 6F 6D wiggy.com 线程异常 “主” javax.net.ssl.SSLHandshakeException:收到致命警报: 握手失败在 sun.security.ssl.Alerts.getSSLException(Alerts.java:192) 在 sun.security.ssl.Alerts.getSSLException(Alerts.java:154) 在 sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1979) 在 sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1086) 在 sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343) 在 org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) 在 org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) 在 org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141) 在 org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) 在 org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) 在 org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) 在 org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) 在 org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) 在 org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) 在 org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) 在 org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) 在 org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) 在 HttpURLConnectionExample.sendGet1(HttpURLConnectionExample.java:83) 在 HttpURLConnectionExample.main(HttpURLConnectionExample.java:48) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:606) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [原始读取]:长度 = 5 0000:15 03 01 00 02 ..... [原始读取]:长度 = 2 0000: 02 28 .( main, READ: TLSv1 Alert, length = 2 main, RECV TLSv1 ALERT: fatal, handshake_failure main,调用 closeSocket() main,处理异常: javax.net.ssl.SSLHandshakeException:收到致命警报: 握手失败

我尝试了很多方法,但无法弄清楚到底是什么问题。

【问题讨论】:

Java 7 不会自动支持 TLS v1.2。见superuser.com/questions/747377/… 对方使用的是什么版本的SSL/TLS?从 Java 7u75 开始,默认禁用 SSLv3,参见:Oracle info 还有来自 Oracle 的一些更有用的信息:Diagnosing TLS, SSL, and HTTPS 你说得对,我在启动参数中添加了 -Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1 ,但仍然是同样的问题。对方是ssllabs.com/ssltest/analyze.html?d=integration.swiggy.com 【参考方案1】:

您的问题是 integration.swiggy.com 和 Java 7 没有共享任何通用密码套件。启用 TLSv1.2 无济于事。

您可以从http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html 下载 Java 7 的 JCE Unlimited Strength Jurisdiction Policy 文件,并将 JRE 的 lib/security 目录下的两个 JAR(local_policy.jar、US_export_policy.jar)替换为下载包中的 JAR。这将添加额外的(更强大的)密码套件,您应该能够连接而无需对代码进行任何更改或启用 TLSv1.2。

作为参考,以下是 Java 7 (1.7.0_79) 中可用的密码套件:

Default Cipher
        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
*       SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
        SSL_DHE_DSS_WITH_DES_CBC_SHA
        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
*       SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
        SSL_DHE_RSA_WITH_DES_CBC_SHA
        SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
        SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
        SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
        SSL_DH_anon_WITH_DES_CBC_SHA
        SSL_DH_anon_WITH_RC4_128_MD5
        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
        SSL_RSA_EXPORT_WITH_RC4_40_MD5
*       SSL_RSA_WITH_3DES_EDE_CBC_SHA
        SSL_RSA_WITH_DES_CBC_SHA
        SSL_RSA_WITH_NULL_MD5
        SSL_RSA_WITH_NULL_SHA
*       SSL_RSA_WITH_RC4_128_MD5
*       SSL_RSA_WITH_RC4_128_SHA
*       TLS_DHE_DSS_WITH_AES_128_CBC_SHA
*       TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
*       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
*       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
        TLS_DH_anon_WITH_AES_128_CBC_SHA
        TLS_DH_anon_WITH_AES_128_CBC_SHA256
*       TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
*       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
        TLS_ECDHE_ECDSA_WITH_NULL_SHA
*       TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
*       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
*       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
        TLS_ECDHE_RSA_WITH_NULL_SHA
*       TLS_ECDHE_RSA_WITH_RC4_128_SHA
*       TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
*       TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
        TLS_ECDH_ECDSA_WITH_NULL_SHA
*       TLS_ECDH_ECDSA_WITH_RC4_128_SHA
*       TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
*       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
        TLS_ECDH_RSA_WITH_NULL_SHA
*       TLS_ECDH_RSA_WITH_RC4_128_SHA
        TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
        TLS_ECDH_anon_WITH_AES_128_CBC_SHA
        TLS_ECDH_anon_WITH_NULL_SHA
        TLS_ECDH_anon_WITH_RC4_128_SHA
*       TLS_EMPTY_RENEGOTIATION_INFO_SCSV
        TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
        TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
        TLS_KRB5_EXPORT_WITH_RC4_40_MD5
        TLS_KRB5_EXPORT_WITH_RC4_40_SHA
        TLS_KRB5_WITH_3DES_EDE_CBC_MD5
        TLS_KRB5_WITH_3DES_EDE_CBC_SHA
        TLS_KRB5_WITH_DES_CBC_MD5
        TLS_KRB5_WITH_DES_CBC_SHA
        TLS_KRB5_WITH_RC4_128_MD5
        TLS_KRB5_WITH_RC4_128_SHA
*       TLS_RSA_WITH_AES_128_CBC_SHA
*       TLS_RSA_WITH_AES_128_CBC_SHA256
        TLS_RSA_WITH_NULL_SHA256

以下是使用 Unlimited Stringth Jurisdiction 策略文件后的内容:

Default Cipher
        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
*       SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
        SSL_DHE_DSS_WITH_DES_CBC_SHA
        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
*       SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
        SSL_DHE_RSA_WITH_DES_CBC_SHA
        SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
        SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
        SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
        SSL_DH_anon_WITH_DES_CBC_SHA
        SSL_DH_anon_WITH_RC4_128_MD5
        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
        SSL_RSA_EXPORT_WITH_RC4_40_MD5
*       SSL_RSA_WITH_3DES_EDE_CBC_SHA
        SSL_RSA_WITH_DES_CBC_SHA
        SSL_RSA_WITH_NULL_MD5
        SSL_RSA_WITH_NULL_SHA
*       SSL_RSA_WITH_RC4_128_MD5
*       SSL_RSA_WITH_RC4_128_SHA
*       TLS_DHE_DSS_WITH_AES_128_CBC_SHA
*       TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
*       TLS_DHE_DSS_WITH_AES_256_CBC_SHA
*       TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
*       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
*       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
*       TLS_DHE_RSA_WITH_AES_256_CBC_SHA
*       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
        TLS_DH_anon_WITH_AES_128_CBC_SHA
        TLS_DH_anon_WITH_AES_128_CBC_SHA256
        TLS_DH_anon_WITH_AES_256_CBC_SHA
        TLS_DH_anon_WITH_AES_256_CBC_SHA256
*       TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
*       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
*       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
*       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
        TLS_ECDHE_ECDSA_WITH_NULL_SHA
*       TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
*       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
*       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
*       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
*       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
        TLS_ECDHE_RSA_WITH_NULL_SHA
*       TLS_ECDHE_RSA_WITH_RC4_128_SHA
*       TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
*       TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
*       TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
*       TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
        TLS_ECDH_ECDSA_WITH_NULL_SHA
*       TLS_ECDH_ECDSA_WITH_RC4_128_SHA
*       TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
*       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
*       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
*       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
*       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
        TLS_ECDH_RSA_WITH_NULL_SHA
*       TLS_ECDH_RSA_WITH_RC4_128_SHA
        TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
        TLS_ECDH_anon_WITH_AES_128_CBC_SHA
        TLS_ECDH_anon_WITH_AES_256_CBC_SHA
        TLS_ECDH_anon_WITH_NULL_SHA
        TLS_ECDH_anon_WITH_RC4_128_SHA
*       TLS_EMPTY_RENEGOTIATION_INFO_SCSV
        TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
        TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
        TLS_KRB5_EXPORT_WITH_RC4_40_MD5
        TLS_KRB5_EXPORT_WITH_RC4_40_SHA
        TLS_KRB5_WITH_3DES_EDE_CBC_MD5
        TLS_KRB5_WITH_3DES_EDE_CBC_SHA
        TLS_KRB5_WITH_DES_CBC_MD5
        TLS_KRB5_WITH_DES_CBC_SHA
        TLS_KRB5_WITH_RC4_128_MD5
        TLS_KRB5_WITH_RC4_128_SHA
*       TLS_RSA_WITH_AES_128_CBC_SHA
*       TLS_RSA_WITH_AES_128_CBC_SHA256
*       TLS_RSA_WITH_AES_256_CBC_SHA
*       TLS_RSA_WITH_AES_256_CBC_SHA256
        TLS_RSA_WITH_NULL_SHA256

integration.swiggy.com 提供的密码套件有:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)   ECDH secp256r1 (eq. 3072 bits RSA)   FS    256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)   ECDH secp256r1 (eq. 3072 bits RSA)   FS    128
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9f)   DH 2048 bits   FS  256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)   DH 2048 bits   FS  128
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)   ECDH secp256r1 (eq. 3072 bits RSA)   FS    256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x6b)   DH 2048 bits   FS  256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39)   DH 2048 bits   FS 256

这些都不在 Java 7 提供的标准密码套件中。但是,最后 4 个是通过 Unlimited Strength Jurisdiction Policy 文件添加的。

【讨论】:

在 jre/lib/security 中添加了两个 JAR,但这里没有发生预期的魔法。有什么选择吗?【参考方案2】:

为了补充 Anand Bhat 的答案,我展示了通过下载 Oracle JDK7 Unlimited Strength 策略 JAR 启用的客户端密码中的差异。但是,即使在 TLSv1.2 下,一些服务器也同意仅使用较新的密码。特别是最新公开的 JDK 7 build 80 不支持“GCM cipher suites”,导致javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8180834

$ diff -U 1000000 -u ciphers-jdk7-80-orig.txt ciphers-jdk7-80-unlimited.txt
--- ciphers-jdk7-80-orig.txt    2019-01-17 16:03:52.328738900 -0500
+++ ciphers-jdk7-80-unlimited.txt       2019-01-17 16:05:37.783770600 -0500
@@ -1,64 +1,81 @@
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ TLS_RSA_WITH_AES_256_CBC_SHA256
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ TLS_RSA_WITH_AES_256_CBC_SHA
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA
  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  TLS_RSA_WITH_AES_128_CBC_SHA256
  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
  TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
  TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
  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
+ TLS_DH_anon_WITH_AES_256_CBC_SHA256
+ TLS_ECDH_anon_WITH_AES_256_CBC_SHA
+ TLS_DH_anon_WITH_AES_256_CBC_SHA
  TLS_DH_anon_WITH_AES_128_CBC_SHA256
  TLS_ECDH_anon_WITH_AES_128_CBC_SHA
  TLS_DH_anon_WITH_AES_128_CBC_SHA
  TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
  SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
  TLS_ECDH_anon_WITH_RC4_128_SHA
  SSL_DH_anon_WITH_RC4_128_MD5
  SSL_RSA_WITH_DES_CBC_SHA
  SSL_DHE_RSA_WITH_DES_CBC_SHA
  SSL_DHE_DSS_WITH_DES_CBC_SHA
  SSL_DH_anon_WITH_DES_CBC_SHA
  SSL_RSA_EXPORT_WITH_RC4_40_MD5
  SSL_DH_anon_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
  SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
  TLS_RSA_WITH_NULL_SHA256
  TLS_ECDHE_ECDSA_WITH_NULL_SHA
  TLS_ECDHE_RSA_WITH_NULL_SHA
  SSL_RSA_WITH_NULL_SHA
  TLS_ECDH_ECDSA_WITH_NULL_SHA
  TLS_ECDH_RSA_WITH_NULL_SHA
  TLS_ECDH_anon_WITH_NULL_SHA
  SSL_RSA_WITH_NULL_MD5
  TLS_KRB5_WITH_3DES_EDE_CBC_SHA
  TLS_KRB5_WITH_3DES_EDE_CBC_MD5
  TLS_KRB5_WITH_RC4_128_SHA
  TLS_KRB5_WITH_RC4_128_MD5
  TLS_KRB5_WITH_DES_CBC_SHA
  TLS_KRB5_WITH_DES_CBC_MD5
  TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
  TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
  TLS_KRB5_EXPORT_WITH_RC4_40_SHA
  TLS_KRB5_EXPORT_WITH_RC4_40_MD5
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

/** Establish a SSL connection to a host and port, writes a byte and
 * prints the response. See
 * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
 */
public class SSLPoke 
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, KeyManagementException 
        if (args.length != 2) 
            System.out.println("Usage: "+SSLPoke.class.getName()+" <host> <port>");
            System.exit(1);
        
        InputStream in = null;
        OutputStream out = null;
        try 
            SSLSocketFactory sslSocketFactory;
            if (true) 
                // https://www.baeldung.com/java-7-tls-v12
                SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
                sslContext.init(null, null, new SecureRandom());

                sslSocketFactory = sslContext.getSocketFactory();
             else 
                sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
                // This will cause an exception on connecting to a TLSv1.2-only server,
                // Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
                //         at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:953)
                //         at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
                //         at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:709)
                //         at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
                //         at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:136)
                //         at SSLPoke.main(SSLPoke.java:66)
                // Caused by: java.io.EOFException: SSL peer shut down incorrectly
                //         at sun.security.ssl.InputRecord.read(InputRecord.java:482)
                //         at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
                //         ... 5 more
            
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(args[0], Integer.parseInt(args[1]));

            // https://gist.github.com/lanimall/cb808a11a058f7fb620a#file-gistfile1-java
            String[] protocols = sslSocket.getSupportedProtocols();

            System.out.println("Supported Protocols: " + protocols.length);
            for(int i = 0; i < protocols.length; i++)
            
                System.out.println(" " + protocols[i]);
            

            protocols = sslSocket.getEnabledProtocols();

            System.out.println("Enabled Protocols: " + protocols.length);
            for(int i = 0; i < protocols.length; i++)
            
                System.out.println(" " + protocols[i]);
            

            String[] ciphers = sslSocket.getSupportedCipherSuites();
            System.out.println("Enabled Ciphers: " + ciphers.length);
            for(int i = 0; i < ciphers.length; i++)
            
                System.out.println(" " + ciphers[i]);
            

            in = sslSocket.getInputStream();
            out = sslSocket.getOutputStream();

            // Write a test byte to get a reaction :)
            out.write(1);

            while (in.available() > 0) 
                System.out.print(in.read());
            
            System.out.println("Successfully connected");

         finally 
            if (in != null) 
                in.close();
            
            if (out != null) 
                out.close();
            
        
    

【讨论】:

以上是关于Java 版本“1.7.0_79”的 SSL 握手失败的主要内容,如果未能解决你的问题,请参考以下文章

Java Paypal 集成 SOAP JAX-WS - SSL 握手异常

jenkins的安装

Tomcat服务器配置https协议(Tomcat HTTPS/SSL 配置)

VisualVM监控JVM

与 SSL 的 mysql jdbc 连接在 tls 握手级别失败

两个数交换