I am trying to consume a restful ws with basic auth. I did not import any cert into my keystore. When I use chrome plugin Advance Rest client
to test it (using basic auth with base64 encoded username:pass). I can see the response back. So far so good.
But when I develop Java code to consume this ws, I get SSL handsake failure:
org.springframework.web.client.ResourceAccessException: I/O error:
Received fatal alert: handshake_failure; nested exception is
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:377)
at test.Rest.main(Rest.java:37) Caused by: 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)
My question is: if the problem is because I did not import cert to my keystore, then both Java code and plugin should not work together. Here, plugin works but my code does not. What is the reason? There is somethings wrong with my code?
Bellow is my code
RestTemplate restTemplate = new RestTemplate();
String plainCreds = "username:pass";
byte[] plainCredsBytes = plainCreds.getBytes(Charset.forName("US-ASCII") );
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
ResponseEntity<String> response =
restTemplate.exchange("https://url",HttpMethod.GET,new
HttpEntity(headers),String.class);
Here is the link to log file:(I have replace my server-name by XXXXXX) http://www.filedropper.com/ssllog
After running: openssl s_client -showcerts -tls1 -connect host:port
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
CONNECTED(00000164)
8088:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:.\ssl\s3_pkt.c:362:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 5 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1452011344
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
and this is the output when i run command openssl s_client -connect server:port
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
CONNECTED(00000164)
depth=0 C = US, ST = "XXXXXX", L = XXXXXX, O = XXXXXX, OU = xxxxx, CN = XXXXXXXXX.test.intranet, emailAddress = xxxxx@xxxxx
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = "XXXXXXX ", L = XXXXX, O = XXXXXX, OU = xxxxxx, CN = XXXXXXXXX.test.intranet, emailAddress = xxxxx@xxxxx
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=US/ST=XXXXXXX /L=XXXXX/O=XXXXXX/OU=XXXXX/CN=XXXXXX.test.intranet/emailAddress=xxxxx@xxxxx
i:/DC=intranet/DC=xxxx/CN=XXXXXX DEV Issuing CA
---
Server certificate
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXX.....
-----END CERTIFICATE-----
subject=/C=US/ST=XXXXXXX /L=XXXXX/O=XXXXXX/OU=XXXXX/CN=XXXXXX.test.intranet/emailAddress=xxxxx@xxxxx
issuer=/DC=intranet/DC=XXX/CN=XXXXX DEV Issuing CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: XXXXX, P-256, 256 bits
---
SSL handshake has read 1895 bytes and written 443 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: 568BF22A5CDBF103155264BBC056B272168AE0777CBC10F055705EB2DD907E5A
Session-ID-ctx:
Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1452012074
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
read:errno=0
RestTemplate provides a synchronous way of consuming Rest services, which means it will block the thread until it receives a response. RestTemplate is deprecated since Spring 5 which means it's not really that future proof. First, we create a Spring Boot project with the spring-boot-starter-web dependency.
The SSLHandshakeException indicates that a self-signed certificate was returned by the client that is not trusted as it cannot be found in the truststore or keystore . This SSLException is seen on the client side of the connection. sun. security.
A TLS/SSL handshake failure occurs when a client and server cannot establish communication using the TLS/SSL protocol. When this error occurs in Apigee Edge, the client application receives an HTTP status 503 with the message Service Unavailable.
From javax.net.debug
log I can see that you are using Java 7 and the client resolves to TLSv1. From openssl
output that your server does not support TLSv1.
TLS ver. 1.1 and 1.2 are disabled in Java 7 by default.
Although SunJSSE in the Java SE 7 release supports TLS 1.1 and TLS 1.2, neither version is enabled by default for client connections. Some servers do not implement forward compatibility correctly and refuse to talk to TLS 1.1 or TLS 1.2 clients. For interoperability, SunJSSE does not enable TLS 1.1 or TLS 1.2 by default for client connections.
Enable TLSv1.1 and TLSv1.2 either by:
JVM argument:
-Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1
Or set the same property from Java code:
System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1");
Or install JCE Unlimited Strength policy files for Java 7. I am not 100% sure if this single step would solve the problem although it is always worth to install JCE while it allows JVM to use stronger versions of existing algorithms.
UPDATE 29/Sep/2016:
Order of protocols changed from better to worse (TLS ver. 1.2 to 1) in options 1 and 2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With