证书和密钥与 openssl 一起使用;他们为什么不在 jks 密钥库中使用 JSSE?

Certificates and keys work with openssl; why don't they work with JSSE in jks keystores?

我得到了 3 个文件:MY.cer、MY.key、B.pem(root、中间证书)。使用 openssl 我获得了成功的连接:

openssl s_client -connect abc.com:10101 -cert MY.cer -key MY.key, -CAfile B.pem

使用 openssl,我们捆绑了 MY.cer 和 MY.key (pkcs12),并使用 keytool 将这对导入 keystore.jks,然后将 B.pem 导入 truststore.jks。我们的 Java SSLConnector 对象(我们在这里到处使用) barfs:

main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, bad_certificate
%% Invalidated:  [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
main, called close()
main, called closeInternal(true)
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
        at sun.security.ssl.Alerts.getSSLException(Unknown Source)
        at sun.security.ssl.Alerts.getSSLException(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
        at com.dam.system.SSLConnector.sendPost(SSLConnector.java:132)

SSLConnector 使用 HttpsUrlConnection 并且对于这个新客户的服务器,我们是第一次看到这个错误。

我们检查了 openssl 调试、javax.ssl 调试、大量搜索、尝试了 portecle 和 InstallCert.java(均显示 bad_certificate)但没有解决。

服务器可能有什么理由认为我们的证书来自 JSSE,但来自 openssl 还不错?

问题完全出在密钥库的创建方式上。

  1. 列表而不是链:客户端、它的根和中间 CA 证书(来自 B.pem 文件)分别导入到 keystore.jks 中(显示为列表) 而不是在链中相互附加。我们使用 kse v5.1.1 删除 CA 证书,然后编辑链并将它们附加回来。

  2. 缺少服务器证书。 truststore.jks 有客户端证书而不是服务器证书。使用 openssl 获取服务器的证书和 keytool 来创建一个新的 truststore.jks.

现在一切正常,无需更改任何 Java 代码。