java 连接到 https 站点时出现 SSLHandshakeException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30350120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SSLHandshakeException while connecting to a https site
提问by Andy Dufresne
I am trying to record a https sitethrough jmeter (version 2.13, java version - 1.8u31) and I am getting SSLHandshakeException while connecting to a https site. The error message is
我正在尝试通过 jmeter(版本 2.13,java 版本 - 1.8u31)记录 https站点,并且在连接到 https 站点时出现 SSLHandshakeException。错误信息是
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2011)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:436)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.jmeter.protocol.http.sampler.MeasuringConnectionManager$MeasuredConnection.open(MeasuringConnectionManager.java:107)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.executeRequest(HTTPHC4Impl.java:517)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:331)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:74)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1146)
at org.apache.jmeter.protocol.http.proxy.Proxy.run(Proxy.java:240)
I have turned on debug logging for SSL but I wasn't able to understand the root cause. It seems that the java client sends the ClientHello but does not receive the ServerHello message (wherethe server chooses the highest version of SSL and the best cipher suite that both the client and server support and sends this information to the client). I see differences between the protocol versions being sent, read and received by the client (TLSv1.1 vs TLSv1.2)
我已经打开了 SSL 的调试日志记录,但我无法理解根本原因。看来,Java客户端发送客户问候,但没有收到的服务器问候消息(其中服务器选择SSL的最高版本,最好的加密套件,无论是客户端和服务器支持,并将该信息发送给客户端)。我看到客户端发送、读取和接收的协议版本之间的差异(TLSv1.1 与 TLSv1.2)
Is this the root cause ? If so, how can I fix it?
这是根本原因吗?如果是这样,我该如何解决?
The logs are pasted here - Java SSLHandshakeException Logs - Pastebin.com
日志粘贴在这里 - Java SSLHandshakeException 日志 - Pastebin.com
Update
更新
As @Anand Bhatt suggested, I analyzed the site with ssllabsand understood the following
正如@Anand Bhatt 所建议的,我用ssllabs分析了该站点并理解了以下内容
- The server does not support TLSv1.2 which is supported by java 8
- The server supports only one cipher suite - TLS_RSA_WITH_AES_256_CBC_SHA
- Java 8u31doesn't support the cipher suite that the server supports and that's most probably the issue.
- 服务器不支持 TLSv1.2,这是由 java 8 支持的
- 服务器仅支持一种密码套件 - TLS_RSA_WITH_AES_256_CBC_SHA
- Java 8u31不支持服务器支持的密码套件,这很可能是问题所在。
Does that sound right? If so, how do we make the java 8 client support the cipher suite that the server supports?
听起来对吗?如果是这样,我们如何让java 8客户端支持服务器支持的密码套件?
回答by dave_thompson_085
SSLlabs is apparently testing "out of the box" support. Java crypto has a crock dating back to the 1990s when the US government severely restricted export of crypto software, and as a result the JRE (or JDK) as distributed by then-Sun now-Oracledoes not permit use of 256-bitsymmetric encryption, which your server is demanding. You must download and install the "JCE Unlimited StrengthJurisdiction Policy Files" for your Java (major) version; 8 is at http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html. The README in the file gives longwinded details, but basically you replace two tiny jar files in JRE/lib/security.
SSLlabs 显然正在测试“开箱即用”的支持。Java 加密的历史可以追溯到 1990 年代,当时美国政府严格限制加密软件的出口,因此当时的 Sun 现在 Oracle 分发的 JRE(或 JDK)不允许使用256 位对称加密,这是您的服务器要求的。您必须为您的 Java(主要)版本下载并安装“ JCE Unlimited StrengthJurisdiction Policy Files”;8 位于http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html。文件中的 README 提供了冗长的细节,但基本上你替换 JRE/lib/security 中的两个小 jar 文件。
TLSv1.2is not a real issue now. TLS protocol automatically negotiates the highest version supported (and enabled) by both ends. Java 8 implementsSSLv3, TLSv1.0, TLSv1.1 and TLSv1.2, but recent updates (8u31 or 7u75 and up) disableSSLv3 by defaultbecause of POODLE; you can re-enable it if you choose, but you should be reluctant to. (Java 7 implements the same protocol versions, but clientby default disables 1.1 and 1.2 because of compatibility concerns at its release several years ago.)
TLSv1.2工作是不是一个真正的问题现在。TLS 协议自动协商两端支持(和启用)的最高版本。Java 8实现了SSLv3、TLSv1.0、TLSv1.1 和 TLSv1.2,但由于 POODLE ,最近的更新(8u31 或 7u75 及更高版本)默认禁用SSLv3 ;如果您愿意,您可以重新启用它,但您应该不愿意。(Java 7 实现了相同的协议版本,但由于几年前发布的兼容性问题,客户端默认禁用 1.1 和 1.2。)
However, because of POODLE and BEAST some security authorities no longer accept SSLv3 and TLSv1.0 as adequately secure; an important example is credit and debit cards, as detailed in https://security.stackexchange.com/a/87077/39571. TLSv1.2 includes some technical improvements over 1.1, making it preferredtoday, and there might be future discoveries that make those improvements crucial; if your server can't support 1.2 (and maybe higher) at that pointyou would be in trouble. Similarly the fact that the server's only supported suite uses plain-RSA key-exchange, i.e. NOT forward secrecy, is considered suboptimal now, and over time may become unacceptable.
但是,由于 POODLE 和 BEAST,一些安全机构不再接受 SSLv3 和 TLSv1.0 作为足够安全;一个重要的例子是信用卡和借记卡,详见https://security.stackexchange.com/a/87077/39571。TLSv1.2 包含一些相对于 1.1 的技术改进,使其成为今天的首选,未来可能会有发现使这些改进变得至关重要;如果您的服务器当时不能支持 1.2(可能更高),您就会遇到麻烦。类似地,服务器唯一支持的套件使用普通 RSA 密钥交换,即非前向保密,现在被认为是次优的,随着时间的推移可能会变得不可接受。
keytool(at least with the normally used keystore and truststore files) has nothing to do with symmetric cryptography. It could likely be relevant if the server uses a CA root(or more exactly and slightly more general, trust anchor) that your JRE and/or application does not trust, and/or if the server wants client authenticationat SSL/TLS level, which is fairly rare. (Most websites authenticate at the web-application level, or at least HTTP level, if at all.) SSLLabs checking of the server cert chain (and several other things also) is generally stricter than Java's, and they didn't complain in thatarea, so it's unlikely you have a problem there.
keytool(至少对于通常使用的密钥库和信任库文件)与对称密码学无关。如果服务器使用您的 JRE 和/或应用程序不信任的CA 根(或更确切地说,更通用的信任锚),和/或如果服务器希望在 SSL/TLS 级别进行客户端身份验证,则这可能是相关的,这是相当罕见的。(至少在Web应用程序级别大多数网站身份验证,或HTTP水平,如果在所有。)SSLLabs服务器证书链(和一些其他的东西也可以)的检查一般是严格比Java的,他们并没有抱怨那区域,因此您不太可能在那里遇到问题。