2017-07-17 91 views
1

我正在java1.8中工作并通过OKHTTP连接到APNS(api.push.apple.com)。Java 1.8:TLSv1.2 ClientHello握手失败(缺少椭圆曲线扩展?)

症状是失败的SSL握手:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure,根据我的研究表明服务器无法与客户端协商密码。

该代码只是通过SSLContext.getInstance("TLS")创建SSL上下文。

-Djavax.net.debug=all运行我的应用程序后,我发现我的SSL握手客户问候看起来是这样的:

*** ClientHello, TLSv1.2 
RandomCookie: GMT: 1500317763 bytes = { 59, 94, 246, 29, 243, 123, 94, 45, 2, 86, 47, 12, 198, 219, 164, 71, 166, 30, 143, 25, 190, 34, 243, 50, 24, 239, 0, 131 } 
Session ID: {} 
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA] 
Compression Methods: { 0 } 
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA 
Extension server_name, server_name: [type=host_name (0), value=api.push.apple.com] 
Extension renegotiation_info, renegotiated_connection: <empty> 
Extension application_layer_protocol_negotiation, protocols: [h2, spdy/3.1, http/1.1] 
*** 

它基本上只是随后进行了

OkHttp https://api.push.apple.com/3/device/token, READ: TLSv1.2 Alert, length = 2 
OkHttp https://api.push.apple.com/3/device/token, RECV TLSv1.2 ALERT: fatal, handshake_failure 

令人费解问题在于代码在同事的笔记本电脑上运行成功 - SSL ClientHello除了包含以下两项外,其他内容都是相同的:

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] 

为APNS服务器(https://www.ssllabs.com/ssltest/analyze.html?d=api.push.apple.com&s=17.188.154.31)SSL分析表明,它仅接受TLSv1.2工作和下面的密码:

TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8) ECDH secp256r1 (eq. 3072 bits RSA) FS 256 
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 

这让我觉得缺少Extension S IN的SSL握手会导致服务器拒绝我的握手,因为没有使用通用密码。


运行此操作系统的笔记本电脑是OS X 10.10,而其中运行的笔记本电脑是macOS 10.12。我们都在Java1.8上。


如果有人有任何线索,这将不胜感激。

谢谢你的时间。

回答

2

可能缺席EC扩展名是什么导致了问题,虽然在技术上它是允许的 - 见RFC 4492第4节:

即提出ECC密码套件可以选择不包括 这些扩展的客户端。在这种情况下,服务器可以自由选择在第5

这仍然可能出错列出的椭圆曲线或点格式中的任何一个 ,但想必没有收到服务器的第一次飞行(服务器问候之前。 .. ServerHelloDone),所以我假设服务器不允许这种缺席。

我认为这是非常奇怪的行为,JDK8不发送该扩展名,所以我期望您的JDK以某种方式进行奇怪的配置,最好安装并测试一个全新的JDK8(未经修改,除了安装“ JCE Unlimited Strength“政策文件)。

我简单看了一下(OpenJDK的)JDK8源,并有为什么这个扩展可能是不存在的几个可能的原因:

  • 不知何故为“EC”的JCE加密服务提供商丢失或没有按” t支持TLS曲线。查看您的jre/lib/security/java.security列表中的security.provider条目,以及您正在编写的任何编程提供程序更改。您是否尝试使用某种硬件令牌进行客户端身份验证?
  • 也许你有“jdk.tls.namedGroups”系统属性集(如果它是空的,你应该看到一个异常,但也许你只列出了不支持的曲线)。检查您可能设置的任何其他系统属性。

根据源代码可能存在的故障产生的找到任何曲线的调试日志行:

 if (debug != null && idList.isEmpty()) { 
     debug.println(
      "Initialized [jdk.tls.namedGroups|default] list contains " + 
      "no available elliptic curves. " + 
      (property != null ? "(" + property + ")" : "[Default]")); 
    } 

请报告你是否看到该消息,并说什么。了解您使用的确切JDK8版本以及您是否启用了FIPS模式也可能会有帮助。