2

I am trying to connect to a https URL hosting a SOAP service via SSL using HttpsURLConnection when i get that error. On debugging in SSL mode, I understand that ClientHello, ServerHello, Certificate, ServerHelloDone, ClientKeyExchange successfully take place. The exception occurs only during the server reply of ChangeCipherSpec stage.

The ssl debug trace is as follows:

*** ClientHello, TLSv1.2
RandomCookie:  
GMT: 1456906493 
bytes = {<some-byte-data>}
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_SHA]
Compression Methods:  { 0 }
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Extension server_name, server_name: [host_name: www4.ipg-online.com]
Extension renegotiation_info, renegotiated_connection: <empty>
***
http-bio-8443-exec-5, WRITE: TLSv1.2 Handshake, length = 110
http-bio-8443-exec-5, READ: TLSv1.2 Handshake, length = 3951
*** ServerHello, TLSv1.2
RandomCookie:  
GMT: 1456906492 
bytes = {<some-byte-data>}
Session ID:  {198, 60, 71, 156, 166, 35, 121, 29, 184, 198, 218, 137, 212, 112, 9, 71, 249, 16, 69, 197, 109, 109, 113, 199, 214, 38, 187, 124, 229, 132, 43, 51}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
** SSL_RSA_WITH_RC4_128_SHA
*** Certificate chain
chain [0] = <this is the hostname certificate which is also present in my keystore>
chain [1] = <blah blah>
chain [2] = <blah blah>
***
Found trusted certificate:
[0] <blah blah> //this is that hostname certificate
*** CertificateRequest
Cert Types: 
RSA
, 
DSS

Supported Signature Algorithms: MD5withRSA, SHA1withRSA, SHA256withRSA
Cert Authorities: <cert details of the hostname cert found in keystore>
*** ServerHelloDone
*** Certificate chain
***
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1.2
http-bio-8443-exec-5, WRITE: TLSv1.2 Handshake, length = 289
SESSION KEYGEN:
PreMaster Secret: <some data>
CONNECTION KEYGEN:
Client Nonce: <some data>
Server Nonce: <some data>
Master Secret: <some data>
Client MAC write Secret: <some data>
Server MAC write Secret: <some data>
Client write key: <some data>
Server write key: <some data>
... no IV derived for this protocol
http-bio-8443-exec-5, WRITE: TLSv1.2 Change Cipher Spec, length = 21
*** Finished
verify_data:  {<some byte data>}
***
http-bio-8443-exec-5, WRITE: TLSv1.2 Handshake, length = 36
http-bio-8443-exec-5, READ: TLSv1.2 Alert, length = 22
http-bio-8443-exec-5
, RECV TLSv1.2 ALERT:  
fatal, 
handshake_failure
%% Invalidated:  [Session-2, SSL_RSA_WITH_RC4_128_SHA]
%% Invalidated:  [Session-3, SSL_RSA_WITH_RC4_128_SHA]
http-bio-8443-exec-5, called closeSocket()
http-bio-8443-exec-5, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert:   handshake_failure
http-bio-8443-exec-5, called close()
http-bio-8443-exec-5, called closeInternal(true)

My environment setting

-Djavax.net.debug=ssl
-Djavax.net.ssl.keyStore=/Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home/jre/lib/security/cacerts
-Djavax.net.ssl.keyStorePassword=<password>
-Dhttps.cipherSuites=SSL_RSA_WITH_RC4_128_SHA

Code

I am using groovy.

String path = "/Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home/jre/lib/security/cacerts"
char[] trustStorePassword = <password>.toCharArray();

InputStream trustStream = new FileInputStream(path);
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStream, trustStorePassword);
trustStream.close()

TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
TrustManager[] trustManagers = trustFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, trustManagers, null);

URL url = new URL(<url-to-server>)
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
String userCredentials = "uname:passwd"
String basicAuth = "Basic " + new String(userCredentials.getBytes().encodeAsBase64())
con.setAllowUserInteraction(true)
con.setRequestProperty("Authorization", basicAuth);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "text/xml");
con.setSSLSocketFactory(sslContext.getSocketFactory());
con.setDoOutput(true)

String urlParameters = "some-xml-data-as-string"
OutputStream wr = con.getOutputStream()
wr.write(urlParameters.getBytes("UTF-8"));
wr.flush();
wr.close();
int responseCode = con.getResponseCode(); //this is where i get exception

1 Answers1

1

... The exception occurs only during the ChangeCipherSpec stage.

The previous messages are missing in your output so one can only guess: since the server sends the alert in the last phase of the handshake, i.e. after the cipher is negotiated and the server has sent its certificate the most likely reason is that the server has requested a certificate from the client which the client either did not provide or which the server did not like. It might be possible that you find more details at some log messages at the server side.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • I have added the entire ssl debug trace. – devesh rastogi Sep 13 '16 at 07:13
  • @deveshrastogi: as expected: one can see the CertificateRequest from the server but the client is not sending the requested certificate. – Steffen Ullrich Sep 13 '16 at 08:12
  • @deveshrastogi: in case you don't have a client certificate get one. In case you have one [How to use SSL with a self-signed certificate in groovy?](http://stackoverflow.com/questions/3242335/how-to-use-ssl-with-a-self-signed-certificate-in-groovy) might help. This is what I've found after a few seconds using a search engine, personally I have no experience with groovy. – Steffen Ullrich Sep 13 '16 at 15:21