通过HTTPS / SSL通过自己的Java客户端连接的问题

我正在尝试与trackobot.com建立连接以接收一些JSON数据。 服务器仅允许通过HTTPS / SSL进行连接。 这是代码:

java.lang.System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); URL url = new URL("https://trackobot.com/profile/history.json?username=USER&token=TOCKEN"); InputStream is = url.openStream(); JsonParser parser = Json.createParser(is); 

openSteam抛出javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure

我阅读了几篇与类似问题相关的post,但这些建议都没有帮助。 相应的证书在我的信任库中。 当我尝试连接到例如google.com时,没有错误。 所以,问题似乎是在我试图连接的服务器的握手特定中。

我使用-Djavax.net.debug = ssl运行我的代码返回:

 keyStore is : keyStore type is : jks keyStore provider is : init keystore init keymanager of type SunX509 trustStore is: /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/security/cacerts trustStore type is : jks trustStore provider is : init truststore [Here I removed hundreds of „adding as trusted cert“:… lines] trigger seeding of SecureRandom done seeding SecureRandom Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false main, setSoTimeout(0) called Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1.1 %% No cached client session *** ClientHello, TLSv1.2 RandomCookie: GMT: 1433943269 bytes = { 109, 198, 189, 148, 62, 6, 19, 126, 179, 214, 250, 99, 207, 117, 162, 47, 62, 176, 222, 247, 98, 29, 155, 63, 255, 100, 171, 187 } Session ID: {} Cipher Suites: [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_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, 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 signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA Extension server_name, server_name: [type=host_name (0), value=trackobot.com] *** main, WRITE: TLSv1.2 Handshake, length = 229 main, READ: TLSv1.2 Alert, length = 2 main, RECV TLSv1.2 ALERT: fatal, handshake_failure main, called closeSocket() main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 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:1991) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1104) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1511) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) at java.net.URL.openStream(URL.java:1038) at trackbot.readHistory(trackbot.java:37) at hsanalytics.main(hsanalytics.java:6) Ende 

此外,我使用openssl和perl脚本(analyze-ssl.pl)来检查服务器。

对于openssl s_client -connect trackobot.com:443我得到了:

 CONNECTED(00000003) depth=2 /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority verify error:num=19:self signed certificate in certificate chain verify return:0 --- Certificate chain 0 s:/C=CH/CN=www.trackobot.com/emailAddress=df1c792ce8e2fc342c0c63c2fab9c6fe-1805689@contact.gandi.net i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA 1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority 2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority --- Server certificate -----BEGIN CERTIFICATE----- MIIGaTCCBVGgAwIBAgIHBaEI9iSK1jANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UE BhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBE aWdpdGFsIENlcnRpZm [...] bnCZTkntRP7wPfw6DpPdJzt8BD0Rpp0B8fVUkqkUujP FEgspzHXqvAp3gzDuNVlElZ4pxSC/06x9xlPua4KnnKIPMVK0DjyXKdPgUaw6YH9 I3SprrGd/B5AoxdPYDM1qRGC+hto3YDnAb29CRFx13mfiEF9En6YrmlZMwJ/dMjo RcvkqpjoxTLODmX9gWgdJ27Ublq/4f/Q9nlVfx4v00eYyqyMYY6IMlOUWEBvWoAv zorzLLY9PmepXJtkCw== -----END CERTIFICATE----- subject=/C=CH/CN=www.trackobot.com/emailAddress=df1c792ce8e2fc342c0c63c2fab9c6fe-1805689@contact.gandi.net issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA --- No client certificate CA names sent --- SSL handshake has read 5848 bytes and written 328 bytes --- New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : DHE-RSA-AES256-SHA Session-ID: A868799D47C550929ADF026FDC48CABD2444C96FDDAB86036196029BF7754D1B Session-ID-ctx: Master-Key: 6C0E428129970C6B1E358E134B12125373BED6FF50D55004A68A9042AD4E51C6D70BB8480266CC1BD1F11B093E212BFC Key-Arg : None Start Time: 1433943895 Timeout : 300 (sec) Verify return code: 0 (ok) --- 

对于analyze-ssl trackobot.com:443我得到了:

 -- trackobot.com port 443 ! server sent unused chain certificate '/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority' ! server sent unused chain certificate '/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority' * maximum SSL version : TLSv1_2 (SSLv23) * supported SSL versions with handshake used and preferred cipher(s): * handshake protocols ciphers * SSLv23 TLSv1_2 ECDHE-RSA-AES256-GCM-SHA384 * TLSv1_2 TLSv1_2 ECDHE-RSA-AES256-GCM-SHA384 * TLSv1_1 TLSv1_1 ECDHE-RSA-AES256-SHA * TLSv1 TLSv1 ECDHE-RSA-AES256-SHA * SSLv3 FAILED: SSL connect attempt failed because of handshake problems error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure * cipher order by : server * SNI supported : ok * certificate verified : ok * chain on 5.102.146.151 * [0/0] bits=2048, ocsp_uri=http://ocsp.startssl.com/sub/class1/server/ca, /C=CH/CN=www.trackobot.com/emailAddress=df1c792ce8e2fc342c0c63c2fab9c6fe-1805689@contact.gandi.net SAN=DNS:www.trackobot.com,DNS:trackobot.com * [1/1] bits=2048, ocsp_uri=http://ocsp.startssl.com/ca, /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA * [2/-] bits=4096, ocsp_uri=, /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority * [-/2] bits=4096, ocsp_uri=, /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority * OCSP stapling : no stapled response * OCSP status : good (soft error: no ocsp_uri for /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority) 

版本:

 Mac OSX 10.10.3 OpenSSL 0.9.8zd 8 Jan 2015 java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode) 

谁能发现我的Java程序失败的地方? 我该怎么做才能满足服务器的握手要求? 我真的是这个问题吗?

根据https://www.ssllabs.com ,服务器支持密码套件

 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 TLS_DHE_RSA_WITH_AES_256_CBC_SHA 

它们被列为“不可用的密码套件”,您可以在调试消息中看到它们。

在JRE / lib / security / local_policy.jar中,我们看到了

 // Some countries have import limits on crypto strength. This policy file // is worldwide importable. grant { permission javax.crypto.CryptoPermission "DES", 64; permission javax.crypto.CryptoPermission "DESede", *; permission javax.crypto.CryptoPermission "RC2", 128, "javax.crypto.spec.RC2ParameterSpec", 128; permission javax.crypto.CryptoPermission "RC4", 128; permission javax.crypto.CryptoPermission "RC5", 128, "javax.crypto.spec.RC5ParameterSpec", *, 12, *; permission javax.crypto.CryptoPermission "RSA", *; permission javax.crypto.CryptoPermission *, 128; }; 

下载并安装“(JCE)Unlimited Strength Jurisdiction Policy Files” – http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html – 我可以确认问题已解决。 读我文件说

由于某些国家/地区的导入控制限制,捆绑在Java运行时环境或JRE(TM),8环境中的JCE策略文件的版本允许使用“强”但有限的加密。 此下载包(包含此README文件的包)提供“无限强度”策略文件,其中不包含对加密强度的限制。

密码套房:[TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,…

您没有Java客户端提供的AES256密码套件。

忽略不可用的密码套件:TLS_RSA_WITH_AES_256_CBC_SHA

因为它们在您的应用程序中不可用。 我不是Java专家,但是这些在Java中不可用,或者需要明确启用它们。 它们是必需的,因为服务器仅支持AES256密码:

  $ perl analyze-ssl.pl -v3 --all-ciphers trackobot.com ... * supported ciphers with SSLv23 handshake * TLSv1_2 ECDHE-RSA-AES256-GCM-SHA384 * TLSv1_2 ECDHE-RSA-AES256-SHA384 * TLSv1_2 ECDHE-RSA-AES256-SHA * TLSv1_2 DHE-RSA-AES256-GCM-SHA384 * TLSv1_2 DHE-RSA-AES256-SHA256 * TLSv1_2 DHE-RSA-AES256-SHA 

由于出口法规的原因,您使用的Java版本可能不支持AES256,请参阅https://knowledge.safe.com/articles/Error_Unexpected_Behavior/Enabling-AES256-in-the-Java-Runtime-Environment-for -单点登录

感谢Steffen Ullrich的tipp,我检查了java提供的密码。 显然,在Java 8中,您的密码没有无限的强度。 例如,在我的情况下,我的程序无法使用服务器所需的AES 256位密码。

为了解决这个问题,oracle提供了一组策略文件,允许无限强度加密。 你可以在这里找到它。

README陈述:

由于某些国家/地区的导入控制限制,捆绑在Java运行时环境或JRE(TM),8环境中的JCE策略文件的版本允许使用“强”但有限的加密。

只需下载软件包并按照安装说明中的说明替换相应的文件即可。 在我这样做之后,握手就像一个魅力。

你可能需要升级你的JDK,我们的Linux服务器上有类似的问题。 我们尝试了不同的方法 似乎没有什么工作,包括安装新的JCE。

JDK中有一个关于SSL连接HostnameVerifier的错误,该错误禁用导致握手失败的SNI扩展: http : //www.oracle.com/technetwork/java/javase/2col/8u141-bugfixes-3720387.html 。

我们升级到最新的jdk 8u162,现在一切都很好看。