'SSLHandshakeException: Received fatal alert: handshake_failure - 2Way SSL
I wrote an Http Client using Apache HttpClient 4.1.13 which call a remote HTTP service using 2way-ssl.
I configured:
- keystore.jks : contains the private key and the client certificate
- keystore password: the password of keystore.jks
- truststore.jks: contains the certificate of CA e intermediate CA of the server
- truststore password: the password of truststore.jks
the code:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(keystore));
try {
keyStore.load(instream, keyStorePassword.toCharArray());
} finally {
instream.close();
}
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
instream = new FileInputStream(new File(trustore));
try {
trustStore.load(instream, trustorePassword.toCharArray());
} finally {
instream.close();
}
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext,
new String[] {"TLSv1.1","TLSv1.2"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
poolingConnManager = new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build());
If I run a java main (JDK Java(TM) SE Runtime Environment (build 1.8.0_231-b11) which does the call, I got a successful connection and I see in the logs
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - Secure session established
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - negotiated protocol: TLSv1.2
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - peer principal: XXXXX
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - peer alternative names: [YYYYY]
[2022-01-25 17:49:18][][][][][main][DEBUG]o.a.h.c.s.SSLConnectionSocketFactory - issuer principal: XXXXX
If I run the same code with the same keystores and passwords in Docker OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)) I got the following handshake error
http-nio-8080-exec-1, READ: TLSv1.2 Alert, length = 2
http-nio-8080-exec-1, RECV TLSv1.2 ALERT: fatal, handshake_failure
%% Invalidated: [Session-1, SSL_NULL_WITH_NULL_NULL]
%% Invalidated: [Session-2, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio-8080-exec-1, called closeSocket()
http-nio-8080-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
[2022-01-25 16:47:45][SESSION_NOT_INITIALIZED][10.60.168.202][http-nio-8080-exec-1] [DEBUG]o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
[2022-01-25 16:47:45][SESSION_NOT_INITIALIZED][10.60.168.202][http-nio-8080-exec-1] [DEBUG]o.a.h.impl.execchain.MainClientExec - Connection discarded
What should I search ? Any hints?
UPDATE: The keystore contains the private key and the certificate chain : certificate -> intermediate CA -> Root CA; I don't understand why the client doesn't find the right certificate to send to the server.
In the working test I got this log
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
matching alias: 1
*** Certificate chain
In the failed test I got:
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
Solution 1:[1]
It was my mistake and the problem was in totally different point. The above code was right.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | pacionet |
