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 握手异常
Tomcat服务器配置https协议(Tomcat HTTPS/SSL 配置)