【发布时间】:2019-02-28 18:55:26
【问题描述】:
我对需要在哪里包含客户端证书感到困惑。现在,我的第一个问题是我不信任服务器。我尝试使用其中包含 Thawte 和 Digicert 的默认 Java 密钥库文件 (cacerts),这些是我尝试与之通信的服务器的根权限。我使用 System.setProperty("javax.net.ssl.keyStore", "...") 将该 cacerts 文件设置为密钥库,它不起作用,我将它设置为信任库,它不起作用。我还有
无法找到请求目标的有效认证路径
所以我使用AlwaysTrustSSLConnectionFactory()暂时解决了这个问题。
现在的问题是服务器不信任我。我有一个客户端证书,我尝试将它添加到密钥库和信任库,但不管我做什么,在 ServerHelloDone 之后我得到了
警告:未找到合适的证书 - 在没有客户端的情况下继续 身份验证
在 Java 的 SSL 调试消息和秘密和密钥消息之后的握手失败中。这是我的日志的结尾:
http-bio-8080-exec-3, WRITE: TLSv1.2 Handshake, length = 40
http-bio-8080-exec-3, READ: TLSv1.2 Alert, length = 2
http-bio-8080-exec-3, RECV TLSv1.2 ALERT: fatal, handshake_failure
%% Invalidated: [Session-7, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
http-bio-8080-exec-3, called closeSocket()
http-bio-8080-exec-3, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
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.https.HttpsURLConnectionImpl.connect(Unknown Source)
这是我当前的代码:
System.setProperty("javax.net.ssl.keyStore", "C:/Users/Lovro/Desktop/certs/api/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "pass");
URL url = new URL(urlRequest);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(new AlwaysTrustSSLContextFactory());
conn.connect();
我从 API 开发人员那里收到了格式为 .p12 的客户端证书,因此我将其转换为 .crt 并使用 Keytool 将其添加到密钥库中。有谁知道可能是什么问题,我的握手失败是因为我没有正确包含客户端证书,或者我没有正确地将它添加到密钥库?据我了解,信任库需要包含受信任的根权限的公钥,并且密钥库应该有我的客户端证书。它是否正确?我如何做到这一点?
欢迎任何建议,我是 TLS/HTTPS 新手,不知道自己在做什么。
【问题讨论】:
-
我忘了说我尝试在
Postman中使用客户端证书并且它有效。证书有效。 -
找不到合适的证书 - 没有客户端身份验证继续意味着客户端在密钥库中找不到服务器发送的 CA 证书列表的匹配证书。然后服务器可能会关闭连接,因为客户端证书尚未发送。确保 .p12 的所有证书和私钥确实导入到 JKS 中,或者直接将 .p12 设置为
javax.net.ssl.keyStore中的密钥库。如果p12也不行,获取服务器发来的CA列表,对比p12证书的颁发者 -
感谢 Pedro,问题是我将 .crt 导入到从原始 .p12 客户端证书创建的密钥库中,因此我实际上只将公钥添加到了我的存储中。菜鸟失误。
标签: java ssl https certificate client-certificates