Java 11 给出不支持的握手消息:server_hello_done 在与客户端证书的 HTTPS 连接上
Java 11 gives Unsupported handshake message: server_hello_done on HTTPS connection with client certificate
我们有一个 Java 小程序(tomcat 下的 运行)可以调用第三方。其中之一使用客户端证书进行身份验证。这在 Java 8 下工作,但我们最近将系统升级到 Java 11,但它不再存在了。错误是
Unsupported handshake message: server_hello_done
(这很奇怪,因为我认为 server_hello_done 是握手的有效部分)
升级后 java 密钥库确实有问题。该服务失败,说它不是有效的 PCKS12 流。使用 keytool 列出内容有效,但有警告
Warning:
The JKS keystore uses a proprietary format. 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"
我们使用了建议的命令,现在可以正常打开密钥库,但出现握手错误。
返回我们代码的堆栈跟踪是:
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)
我们正在使用 apache http 客户端 (org.apache.http.impl.client.CloseableHttpClient)。堆栈跟踪中的下一行只是在我们的代码中调用 client.execute()
。
还包括
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)
第三方确认他们在日志中看到 "no shared cipher",但表示他们支持广泛的密码 ("SSL3, TLS 1.0, 1.1, or 1.2. Ciphers are marked as HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH")。我认为我们支持除 SSL3 之外的大部分内容。据我所知,我们在 java 11 中有默认设置。尝试暂时激活 SSLv3 但无法连接(尽管自从尝试我根本无法从该机器连接(超时)即使在恢复之后,所以这可能不会说太多 - 我尝试从测试机器而不是生产机器那个)。
有什么想法吗?我是在正确的路线上继续查看密码还是我遗漏了什么?
原来只需要重启tomcat!但是,因为这是一个生产服务器做很多事情我不想做第一步。但它修复了它。
我对发生的事情的最佳猜测是:
- 更新后的 java 版本的密钥库格式错误
- 尝试使用无效的密钥库使 tomcat/java 进入某种奇怪的状态
- 更新密钥库允许 java 使用它,但它仍然处于某种奇怪的状态
- 重新启动修复它。
真正奇怪的是,即使针对不同的 IP(我尝试针对第三方的测试服务器)和不同的密钥库(我制作了更新的密钥库的副本并做了一个请求,它的行为方式也是一样的用那个)。最初的错误是 "Stream is not a valid PKCS12 keystore" 并且堆栈跟踪返回到试图在我们的代码中打开密钥库的行。修复了密钥库格式后,它在我们的代码中走得更远(堆栈跟踪现在返回到 client.execute()
)但它失败了,并显示 _Unsupported 握手消息:server_hello_done_。
我创建了整个 tomcat 文件夹(包括 jre)的副本,最初使用原始(无效)密钥库,将其更改为另一个端口上的 运行 并在此旁边启动它tomcat 在同一台机器上。它的行为相同,但在重新启动后工作。今天早上我重新启动了主要服务,现在它可以工作了
我们有一个 Java 小程序(tomcat 下的 运行)可以调用第三方。其中之一使用客户端证书进行身份验证。这在 Java 8 下工作,但我们最近将系统升级到 Java 11,但它不再存在了。错误是
Unsupported handshake message: server_hello_done
(这很奇怪,因为我认为 server_hello_done 是握手的有效部分)
升级后 java 密钥库确实有问题。该服务失败,说它不是有效的 PCKS12 流。使用 keytool 列出内容有效,但有警告
Warning:
The JKS keystore uses a proprietary format. 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"
我们使用了建议的命令,现在可以正常打开密钥库,但出现握手错误。
返回我们代码的堆栈跟踪是:
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)
我们正在使用 apache http 客户端 (org.apache.http.impl.client.CloseableHttpClient)。堆栈跟踪中的下一行只是在我们的代码中调用 client.execute()
。
还包括
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)
第三方确认他们在日志中看到 "no shared cipher",但表示他们支持广泛的密码 ("SSL3, TLS 1.0, 1.1, or 1.2. Ciphers are marked as HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH")。我认为我们支持除 SSL3 之外的大部分内容。据我所知,我们在 java 11 中有默认设置。尝试暂时激活 SSLv3 但无法连接(尽管自从尝试我根本无法从该机器连接(超时)即使在恢复之后,所以这可能不会说太多 - 我尝试从测试机器而不是生产机器那个)。
有什么想法吗?我是在正确的路线上继续查看密码还是我遗漏了什么?
原来只需要重启tomcat!但是,因为这是一个生产服务器做很多事情我不想做第一步。但它修复了它。
我对发生的事情的最佳猜测是:
- 更新后的 java 版本的密钥库格式错误
- 尝试使用无效的密钥库使 tomcat/java 进入某种奇怪的状态
- 更新密钥库允许 java 使用它,但它仍然处于某种奇怪的状态
- 重新启动修复它。
真正奇怪的是,即使针对不同的 IP(我尝试针对第三方的测试服务器)和不同的密钥库(我制作了更新的密钥库的副本并做了一个请求,它的行为方式也是一样的用那个)。最初的错误是 "Stream is not a valid PKCS12 keystore" 并且堆栈跟踪返回到试图在我们的代码中打开密钥库的行。修复了密钥库格式后,它在我们的代码中走得更远(堆栈跟踪现在返回到 client.execute()
)但它失败了,并显示 _Unsupported 握手消息:server_hello_done_。
我创建了整个 tomcat 文件夹(包括 jre)的副本,最初使用原始(无效)密钥库,将其更改为另一个端口上的 运行 并在此旁边启动它tomcat 在同一台机器上。它的行为相同,但在重新启动后工作。今天早上我重新启动了主要服务,现在它可以工作了