简体   繁体   English

Java 11给出了不支持的握手消息:HTTPS与客户端证书的连接上的server_hello_done

[英]Java 11 gives Unsupported handshake message: server_hello_done on HTTPS connection with client certificate

We have a Java applet (running under tomcat) which makes calls to third parties. 我们有一个Java小程序(在tomcat下运行),可以调用第三方。 One of them uses a client certificate to authenticate. 其中之一使用客户端证书进行身份验证。 This was working under Java 8, but we recently upgraded the system to Java 11 and it doesn't any more. 这是在Java 8下工作的,但是我们最近将系统升级到了Java 11,现在已经不行了。 The error is 错误是

Unsupported handshake message: server_hello_done 不支持的握手消息:server_hello_done

(which is odd, since I thought server_hello_done was a valid part of the handshake) (这很奇怪,因为我认为server_hello_done是握手的有效部分)

We did have an issue with the java keystore after upgrade. 升级后,Java密钥库确实存在问题。 The service failed saying it wasn't a valid PCKS12 stream. 服务失败,因为它不是有效的PCKS12流。 Listing the contents with keytool worked, but with warning 使用keytool列出内容是可行的,但带有警告

Warning: 警告:

The JKS keystore uses a proprietary format. JKS密钥库使用专有格式。 It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore /path/to/keystore -destkeystore /path/to/keystore -deststoretype pkcs12" 建议使用“ keytool -importkeystore -srckeystore / path / to / keystore -destkeystore / path / to / keystore -deststoretype pkcs12”迁移到行业标准格式PKCS12。

We used the suggested command and it now opens the keystore OK, but we get the handshake error. 我们使用了建议的命令,现在它打开了密钥库OK,但是出现了握手错误。

The stack trace back to our code is: 追溯到我们的代码的堆栈是:

Unsupported handshake message: server_hello_done
javax.net.ssl.SSLProtocolException: Unsupported handshake message: server_hello_done
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:126)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:446)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)

We are using the apache http client (org.apache.http.impl.client.CloseableHttpClient). 我们正在使用apache http客户端(org.apache.http.impl.client.CloseableHttpClient)。 The next line in the stack trace is simply a call to client.execute() in our code. 堆栈跟踪的下一行只是对我们代码中的client.execute()的调用。

It also includes 它还包括

Caused by: java.lang.UnsupportedOperationException: Not supported yet.
        at java.base/sun.security.ssl.HandshakeHash$CloneableHash.archived(HandshakeHash.java:616)
        at java.base/sun.security.ssl.HandshakeHash$T12HandshakeHash.archived(HandshakeHash.java:546)
        at java.base/sun.security.ssl.HandshakeHash.archived(HandshakeHash.java:188)
        at java.base/sun.security.ssl.CertificateVerify$T12CertificateVerifyMessage.<init>(CertificateVerify.java:581)
        at java.base/sun.security.ssl.CertificateVerify$T12CertificateVerifyProducer.produce(CertificateVerify.java:740)
        at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
        at java.base/sun.security.ssl.ServerHelloDone$ServerHelloDoneConsumer.consume(ServerHelloDone.java:173)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)

The third party confirms they see "no shared cipher" in their logs, but say they support a broad range of ciphers ( "SSL3, TLS 1.0, 1.1, or 1.2. Ciphers are marked as HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH" ). 第三方确认他们在日志中看到“没有共享密码”,但表示他们支持各种密码( “ SSL3,TLS 1.0、1.1或1.2。密码被标记为HIGH:MEDIUM:!aNULL:!eNULL: @STRENGTH” )。 I think we support most of that except SSL3. 我认为我们支持除SSL3之外的大多数内容。 As far as I know we have default settings in java 11 for such. 据我所知,我们在Java 11中有默认设置。 Tried activating SSLv3 temporarily but couldn't connect (although since trying that i can't connect from that machine at all (times out) even after reverting, so that may not say much - I tried from a test machine not the production one for that). 尝试暂时激活SSLv3,但无法连接(尽管尝试恢复后即使连我都无法从该计算机连接(超时),所以这可能不多说-我从一台测试计算机而不是生产计算机尝试过)那)。

Any ideas? 有任何想法吗? Am I on the right lines to keep looking at ciphers or is there something I'm missing? 我是在正确的路线上继续查看密码还是我缺少什么?

It turned out that all that was needed was a restart of tomcat! 原来,所需要做的只是重启tomcat! But, since this was a production server doing many things I didn't want to do that as step one. 但是,由于这是一台生产服务器,需要执行许多操作,所以我不想在第一步中这样做。 But it fixed it. 但是它解决了。

My best guess as to what happened was: 关于发生的事情,我最好的猜测是:

  • The keystore was in the wrong format for the updated java version 对于更新的Java版本,密钥库的格式错误
  • The attempt to use the invalid keystore put tomcat/java into some weird state 尝试使用无效的密钥库使tomcat / java处于某种奇怪的状态
  • Updating the keystore allowed java to use it, but it was still in some weird state 更新密钥库允许Java使用它,但是它仍然处于某种奇怪的状态
  • Restart fixed it. 重新启动修复它。

What is really weird is that it behaved the same way even against a different IP (I tried against the third party's Test server) and with a different keystore (I made a copy of the updated keystore and did a request which used that). 真正奇怪的是,即使针对不同的IP(我针对第三方的测试服务器尝试)和具有不同的密钥库(我制作了更新的密钥库的副本并发出使用该密钥库的请求),它的行为也相同。 The initial error was "Stream is not a valid PKCS12 keystore" and the stack trace went back to the line that tried to open the keystore in our code. 最初的错误是“ Stream不是有效的PKCS12密钥库” ,并且堆栈跟踪返回到试图在我们的代码中打开密钥库的行。 Having fixed the keystore format, it got further in our code (stack trace now went back to client.execute() ) but it failed with _Unsupported handshake message: server_hello_done_. 修复了密钥库格式之后,它在我们的代码中有了更进一步的处理(堆栈跟踪现在返回到client.execute() ),但是失败了,返回了_Unsupported握手消息:server_hello_done_。

I created a copy of the whole tomcat folder (including jre), with initially the original (invalid) keystore, changed it to run on another port and started it up next to this tomcat on the same machine. 我创建了整个tomcat文件夹(包括jre)的副本,最初带有原始的(无效的)密钥库,将其更改为在另一个端口上运行,然后在同一台机器上的该tomcat旁边启动了它。 It behaved the same but then worked after a restart. 它的行为相同,但是重新启动后可以工作。 This morning i restarted the main service and now it works 今天早上,我重新启动了主要服务,现在可以使用了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM