Apache httpclient javax.net.ssl.SSLHandshakeException:
我正在尝试连接到具有SSLv3安全性的服务。
在提供以下文件后,通信可与curl和浏览器一起使用
1 2 3 | 1. ca.crt 2. private.key 2. client.crt |
我使用了所有3个文件来创建具有以下cmd
的ssl密钥库
1 | openssl pkcs12 -export -in client.crt -inkey private.key -CAfile ca.crt -out sslstore.p12 |
然后使用keytool将其导入为java truststore
1 | keytool -importkeystore -srckeystore sslstore.p12 -srcstoretype PKCS12 -destkeystore truststore.jks |
之后,我将跟随以下链接https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java
连接到URL。仅将协议从TLSv1更改为SSLv3。
我总是在连接时得到javax.net.ssl.SSLHandshakeException:例外。
如前所述,这些键适用于curl /浏览器。
EDIT-2
在SSLContexts.custom()
附近更改代码
来自:
1 2 3 | sslcontext = SSLContexts.custom() .loadTrustMaterial(keyStore, new TrustSelfSignedStrategy()) .build(); |
至:
1 2 3 4 | sslcontext = SSLContexts.custom() .loadKeyMaterial(keyStore,"changeit".toCharArray()) .loadTrustMaterial(keyStore, new TrustSelfSignedStrategy()) .build(); |
工作。请注意,我使用的是相同的密钥库。
EDIT-1
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public static void main (String[] args) throws KeyStoreException, FileNotFoundException { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("certs/ppro.jks"); try { keyStore.load(is,"changeit".toCharArray()); } catch (IOException | NoSuchAlgorithmException | CertificateException e) { e.printStackTrace(); } // Trust own CA and all self-signed certs SSLContext sslcontext = null; try { sslcontext = SSLContexts.custom() .loadTrustMaterial(keyStore, new TrustSelfSignedStrategy()) .build(); } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } try { sslcontext.loadKeyMaterial(keyStore,"changeit".toCharArray()); } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } // Allow TLSv1 protocol only SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, new String[] {"SSLv3" } , null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); try (CloseableHttpClient httpclient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build()) { HttpPost httpPost = new HttpPost(URL); try { CloseableHttpResponse response = httpclient.execute(httpPost); System.out.println(response); } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } |
EDIT-0
这是来自Java的堆栈跟踪,包括一些ssl调试信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | *** ClientKeyExchange, RSA PreMasterSecret, SSLv3 main, WRITE: SSLv3 Handshake, length = 132 SESSION KEYGEN: PreMaster Secret: 0000: 03 00 E7 89 C2 9D AB 1A 3B 75 85 5B 4E C6 EE 10 ........;u.[N... 0010: 83 0F 3C 37 74 3C D0 6A AF 51 D7 EC E2 B9 50 35 ..<7t<.j.Q....P5 0020: CC 8D 58 93 39 5D B6 4F BE DB 5A F4 E3 0A BE 42 ..X.9].O..Z....B CONNECTION KEYGEN: Client Nonce: 0000: 53 47 9A BD 4B 14 BC AF B0 2B FB 6C 49 9C E4 53 SG..K....+.lI..S 0010: 21 F3 53 C8 7F 74 1C 5C C0 5E 6D 67 18 50 10 4D !.S..t.\\.^mg.P.M Server Nonce: 0000: 53 47 9A BD B2 5C 44 89 92 BE 4B FF F4 F6 60 FE SG...\\D...K...`. 0010: D6 18 67 96 6A 13 3C 80 9F D2 56 29 1A 60 B4 E4 ..g.j.<...V).`.. Master Secret: 0000: E3 E5 11 9F 87 B6 A3 4E 8C 9C F1 20 E9 A5 50 62 .......N... ..Pb 0010: DD E8 E6 A3 61 FC C0 56 0C 1E A8 29 BC F4 5C 52 ....a..V...)..\ 0020: DE CE 98 64 0E 57 07 E6 22 24 08 1A 77 8A 97 48 ...d.W.."$..w..H Client MAC write Secret: 0000: 44 98 8B 9C C4 59 C2 4E 21 66 67 6D 96 C4 FE 9C D....Y.N!fgm.... 0010: 2B 74 AD 61 +t.a Server MAC write Secret: 0000: 29 7D 5A F2 71 B6 55 C0 CF BB 82 66 02 03 B1 35 ).Z.q.U....f...5 0010: 5A 69 83 99 Zi.. Client write key: 0000: B5 32 F7 7C DC DB 4F B4 00 48 66 A4 B3 C0 7D 6B .2....O..Hf....k Server write key: 0000: CB 80 F4 76 53 92 6F 87 3B A3 9D B2 A9 6F 40 85 ...vS.o.;....o@. Client write IV: 0000: B7 89 4A FC 43 7A 1B 3C DD 83 7F CE A1 FC FB BF ..J.Cz.<........ Server write IV: 0000: 84 92 B7 B4 EB 13 B6 77 EF 87 B0 E1 04 41 5C 4D .......w.....A\\M main, WRITE: SSLv3 Change Cipher Spec, length = 1 *** Finished verify_data: { 116, 66, 54, 146, 216, 200, 254, 221, 170, 236, 204, 2, 17, 139, 161, 37, 205, 117, 131, 95, 255, 123, 158, 100, 150, 110, 105, 209, 22, 205, 31, 196, 95, 84, 59, 252 } *** main, WRITE: SSLv3 Handshake, length = 64 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254) at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106) at com.masterpayment.frontend.gateway.beconnector.GiroGateClient.main(GiroGateClient.java:66) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) main, READ: SSLv3 Alert, length = 2 main, RECV SSLv3 ALERT: fatal, handshake_failure %% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA] main, called closeSocket() main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure |
apache示例仅设置一个信任库。那只会使用CA证书。您还需要设置一个"身份"来处理客户端证书。我意识到您将它们全部放在同一个Java密钥库中,并且可能仍然可以(但通常它们位于单独的文件中)。
该示例调用loadTrustMaterial()。您还需要调用loadKeyMaterial()。
我的直觉是您遇到PKIX链验证错误-请尝试以下操作:
1 2 3 4 5 6 7 | openssl pkcs12 \\ -export \\ -chain \\ -in client.crt \\ -inkey private.key \\ -CAfile ca.crt \\ -out sslstore.p12 |
请注意上述-我已经添加了'-chain \\'选项-这应该使用适当的证书链将证书正确导出到PKCS#12存档中。
在过去的6个月里,我遇到的次数超过了我所能计数的次数,它总是让我受益。
如果这不起作用,请也从Java添加一些堆栈跟踪。