我对于到底需要在哪里包含客户证书感到困惑。现在,我的第一个问题是我不信任服务器。我尝试使用默认的Java密钥库文件(证书),该文件中同时包含Thawte和Digicert,这些文件是我要与之通信的服务器的根权限。我使用System.setProperty("javax.net.ssl.keyStore", "...")
将该cacerts文件设置为密钥存储,它不起作用,我将其设置为truststore,它不起作用。我仍然有
找不到到所请求目标的有效认证路径
所以我使用AlwaysTrustSSLConnectionFactory()
暂时解决了这个问题。
现在的问题是服务器不信任我。我有一个客户端证书,我尝试将其添加到密钥库和信任库中,但是无论我做什么,在ServerHelloDone之后我都会得到
Java的SSL调试消息中的警告:找不到合适的证书-在没有客户的情况下继续 认证
以及秘密和密钥消息后的握手失败。这是我日志的结尾:
http-bio-8080-exec-3, READ: TLSv1.2 Handshake, length = 333
*** ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: Sun EC public key, 256 bits
public x coord: 98538070232466209510508111485778316025052762596580196398964623226311407167077
public y coord: 115064641147496698382202313215933439469086519002181671334211217988795069727259
parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
http-bio-8080-exec-3, READ: TLSv1.2 Handshake, length = 117
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withRSA, Unknown (hash:0x6, signature:0x2), SHA512withECDSA, SHA384withRSA, Unknown (hash:0x5, signature:0x2), SHA384withECDSA, SHA256withRSA, SHA256withDSA, SHA256withECDSA, Unknown (hash:0x3, signature:0x1), Unknown (hash:0x3, signature:0x2), Unknown (hash:0x3, signature:0x3), SHA1withRSA, SHA1withDSA, SHA1withECDSA
Cert Authorities:
<CN=test, O=test>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
*** ECDHClientKeyExchange
ECDH Public value: { 4, 27, 38, 123, 80, 37, 162, 101, 222, 228, 249, 225, 170, 123, 245, 118, 154, 198, 134, 128, 105, 222, 20, 31, 183, 237, 163, 35, 13, 205, 219, 241, 43, 132, 49, 107, 207, 71, 25, 241, 130, 82, 194, 153, 140, 243, 105, 178, 174, 151, 108, 57, 63, 166, 138, 93, 70, 56, 244, 199, 166, 104, 183, 4, 78 }
http-bio-8080-exec-3, WRITE: TLSv1.2 Handshake, length = 77
SESSION KEYGEN:
PreMaster Secret:
0000: 6E 2D CC 68 0D 92 38 2F 67 B8 D7 C8 3B 72 8B 65 n-.h..8/g...;r.e
0010: 82 04 4B 63 67 38 BB D3 96 ED 1A 49 61 11 7B E2 ..Kcg8.....Ia...
CONNECTION KEYGEN:
Client Nonce:
0000: 5B A9 E3 1C 95 8B 8A 3A D2 F7 65 7B DC 34 53 0E [......:..e..4S.
0010: AC 24 4C AE 95 F9 EF 27 1F F1 1F 11 0E 05 E8 1E .$L....'........
Server Nonce:
0000: 11 DE 45 EB B6 63 F1 7B DF E6 DC A8 34 85 D4 07 ..E..c......4...
0010: FE 61 EB CB 5D CA 3D D9 5B 26 56 B0 60 61 A4 9E .a..].=.[&V.`a..
Master Secret:
0000: 4B 47 2B E9 84 38 18 D7 F2 A9 81 6B 3B 12 B9 FB KG+..8.....k;...
0010: 18 D5 30 C9 9A 11 C5 D5 C8 5B 91 03 00 08 B1 F4 ..0......[......
0020: CD D7 56 6C 9A 80 1C 85 BD 7C 9A DF 40 9F AE 64 ..Vl........@..d
... no MAC keys used for this cipher
Client write key:
0000: F7 E3 C7 06 53 55 06 35 84 71 42 FA F7 0A AD ED ....SU.5.qB.....
0010: F4 AE B4 BD 79 C7 79 FD F5 84 F7 48 42 0D 6F 10 ....y.y....HB.o.
Server write key:
0000: 98 95 3F DB C6 E6 DC 4C 4B 03 F6 FF E4 C6 C1 28 ..?....LK......(
0010: F4 08 C9 29 C2 2F 25 4F 4E 1D 7A 0D 74 F0 1C FC ...)./%ON.z.t...
Client write IV:
0000: 5B FA EF 63 [..c
Server write IV:
0000: 36 72 AE 18 6r..
http-bio-8080-exec-3, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 255, 41, 51, 7, 96, 87, 163, 245, 51, 86, 110, 34 }
***
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的新手,也不知道我在做什么。
答案 0 :(得分:1)
我从API开发人员那里收到了.p12格式的客户证书,因此我将其转换为.crt并将其添加到使用Keytool的密钥库中
这是您出错的地方。将其转换为.crt会提取公共证书。您需要做的是将.p12文件转换到Java密钥库。网上有很多例子。参见this SO answer。
要确认它是否有效,请运行keytool -list -keystore <yourkeystore>.jks
,并检查其中是否有PrivateKeyEntry
。
您在检查内容时,请在-v
命令中添加keytool -list
标志,并检查Issuer字段是否为CN=test, O=test
,因为我们可以从您的日志文件中看到您的服务器需要由该机构颁发的客户证书。
还请检查JDK是否配置了无限制强度管辖权Policy Files,因为要求您使用的密码要求使用它。
答案 1 :(得分:-1)
从日志来看,似乎TLS密码TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
对于TLS客户端无效。您可能需要检查客户端支持哪些密码列表。如果密码列表中未包含密码TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
,则可能需要添加对它的支持。
http-bio-8080-exec-3,读取:TLSv1.2警报,长度= 2
http-bio-8080-exec-3,RECV TLSv1.2警报:致命,handshake_failure
%%无效:[会话7,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]