关于java:Apache httpclient javax.net.ssl.SSLHandshakeException:

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添加一些堆栈跟踪。