【问题标题】:Java 8 SSL Handshake failureJava 8 SSL 握手失败
【发布时间】:2018-03-31 02:39:58
【问题描述】:

我们正在为我们的数据库 (12c) 流量使用 SSL。使用 JDBC 客户端(Java 1.8.0_65,ojdbc7)连接到数据库时,握手失败。我们的数据库服务器使用SSL_RSA_WITH_AES_128_CBC_SHA256 密码。

java.sql.SQLRecoverableException: IO Error: Received fatal alert: handshake_failure
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:752) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566) ~[ojdbc7.jar:12.1.0.2.0]
        at java.sql.DriverManager.getConnection(DriverManager.java:664) ~[?:1.8.0_65]
        at java.sql.DriverManager.getConnection(DriverManager.java:247) ~[?:1.8.0_65]
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[?:1.8.0_65]
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[?:1.8.0_65]
        at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023) ~[?:1.8.0_65]
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125) ~[?:1.8.0_65]
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) ~[?:1.8.0_65]
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747) ~[?:1.8.0_65]
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123) ~[?:1.8.0_65]
        at oracle.net.ns.Packet.send(Packet.java:419) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.net.ns.ConnectPacket.send(ConnectPacket.java:241) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.net.ns.NSProtocolStream.negotiateConnection(NSProtocolStream.java:157) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.net.ns.NSProtocol.connect(NSProtocol.java:264) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1452) ~[ojdbc7.jar:12.1.0.2.0]
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:496) ~[ojdbc7.jar:12.1.0.2.0]

为了分析,我们启用了 ssl 调试,发现如下:

 *** ClientHello, TLSv1
RandomCookie:  GMT: 1491604703 bytes = { 8, 77, 210, 159, 243, 108, 135, 13, 187, 223, 121, 238, 236, 46, 76, 255, 76, 12, 130, 135, 233, 99, 154, 136, 70, 38, 132, 176 }
Session ID:  {223, 118, 94, 151, 92, 90, 47, 206, 76, 197, 24, 27, 241, 230, 236, 184, 87, 216, 9, 178, 99, 207, 38, 169, 193, 168, 99, 17, 211, 45, 239, 31}
Cipher Suites: [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_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_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]
***
main, WRITE: TLSv1 Handshake, length = 183
main, READ: TLSv1 Handshake, length = 81

我们可以看到java客户端不支持SSL_RSA_WITH_AES_128_CBC_SHA256密码。所以我们已经安装了 JDK8 Unlimited Strength Jars。即使在那之后,Java 客户端也不支持SSL_RSA_WITH_AES_128_CBC_SHA256 密码。

我的查询是:

  1. 由于密码使用的是 256 位算法,一旦我提供了 Unlimited Strength Jars,为什么 Java 客户端仍然不支持上述密码。

  2. 正如我从 Oracle Docs here 中看到的那样,JDK 1.8 默认支持上述密码。那么为什么Java客户端没有显示它忽略了上面的密码。

我没有得到我在这里缺少的东西。对此的任何指导都非常感谢。

编辑

正如评论中建议的那样,使用 ojdbc1.8 解决了这个问题。但是,我对此还有几个问题:

  1. 我可以看到,握手现在发生在 TLSv1.2 上,之前它发生在 TLSv1 上。我从this link 了解到的是JDK 1.8 默认支持TLSv1.2。为什么它以前不使用相同的。

  2. 与密码套件相关,现在使用 ojdbc8,正在传递其他密码,其中还包括 SSL_RSA_WITH_AES_128_CBC_SHA256 密码,而这在 ojdbc7 jar 之前是不存在的。这个Oracle 链接说JDK 1.8 默认支持这个密码。但最初,它不支持 ojdbc7。我也不明白这一点以及制作 ojdbc8 有何不同。

【问题讨论】:

  • 在 java 1.8 中使用 ojdbc7(而不是 ojdbc8)的任何原因?也许这就是问题所在......
  • @Cyphrags 没有使用 ojdbc7 jar 的具体原因。它在服务器中,所以我们正在使用它。我换成ojdbc8.jar试试。
  • 您确定客户端使用的是 Java 1.8 吗?我本来希望来自 Java 1.8 的 TLSv1.2 ClientHello。
  • 你不需要'无限的力量'; AES-128 不超过 128,SHA256 不加密。但是 SHA256 套件确实需要 TLSv1.2,并且您的客户端出于某种原因仅提供 TLSv1.0,即使 j8 应该默认为 TLSv1.2(如 EJP 所说)。再加上它已经有一个 sessionid,这应该只在恢复时发生;您确定这是您跟踪中的第一个相关信息吗?并且 read length=81 对于警报来说太大了;你确定在这之后但在失败之前没有任何东西吗?
  • 显然 ojdbc7.jar 做了一些限制 TLS 协议的事情。如果是这样,为什么是个谜。

标签: java tls1.2


【解决方案1】:

将使用的库更改为 ojdbc8 解决了该问题。

【讨论】:

  • 感谢您的回答。即使它解决了问题,我也不能接受这个作为已接受的答案,因为这没有对我的问题提供任何解释,也没有提供任何关于“如何”的详细解释,我正在寻找。
  • 问题是我无法回答“为什么” - 我需要源代码,正如 OTN 许可证中所述:“此外,您可能不会:[...] 原因或允许对程序进行逆向工程(除非法律要求互操作性)、反汇编或反编译;和"
  • 并且(可能)ojdbc 7 使用了一个或多个变量或函数,这些变量或函数很可能在 Java 1.8 中发生了变化
  • 但是,我理解你的决定,也许有人可以详细解释那里发生的事情:)
【解决方案2】:

上述错误是由于 Oracle bug 19030178。这个SO link 详细解释了这些步骤。

ojdbc7 jar 中,我们为bug 19030178 应用了补丁并添加了所需的-D 参数。通过这些更改,它可以正常工作。

【讨论】:

    【解决方案3】:

    针对错误 19030178 的修补 ojdbc7.jar 位于 OTN。你可以下载这个,也可以使用 12.2 驱动程序。

    另外,参考这篇帖子"Database Connectivity over TLSv1.2 using JDBC thin and JKS"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-27
      • 1970-01-01
      • 2018-07-28
      • 2012-10-11
      • 2015-03-16
      • 2021-12-28
      相关资源
      最近更新 更多