1

I am using a 2 way ssl authentication to post data securely. The client has given me their certificates which i loaded into the truststore and my server certificate which they generated after i gave them my CSR. I have loaded my server cert into the keystore. My code is accepting their certificates, sending the key but not the server certificate. Code used is as below. Kindly assist;

Error: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure.

Reason: Empty certificate passed.

public static String DoMyPost(String URL, String requestData, String transactID)
        throws MalformedURLException, Exception {
    System.out.println("DoMyPost(): Start");
    String strResponse = "";
    URL url = new URL(URL);
    try {
        HostnameVerifier hv = new HostnameVerifier() {
         @Override
         public boolean verify(String urlHostName, SSLSession session) {
         return true;
         }
         };
        System.setProperty("javax.net.ssl.keyStore", "C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1.jks");
        System.setProperty("javax.net.ssl.keyStorePassword", "wasp123");
        System.setProperty("javax.net.ssl.keyStoreType", "JKS");

        System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1TrustStore");
        System.setProperty("javax.net.ssl.trustStorePassword", "wasp123");
        System.setProperty("javax.net.debug", "all");

        //CertificateFactory factory2 = CertificateFactory.getInstance("X.509");
        //Certificate generateCertificate = factory2.generateCertificate(new FileInputStream("C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1.cer"));
        KeyStore ks = KeyStore.getInstance("JKS");
        InputStream certK = new FileInputStream("C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1.jks");
        ks.load(certK, "wasp123".toCharArray());
        //ks.setCertificateEntry("testserver1cert", generateCertificate);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, "wasp123".toCharArray());

        KeyStore truststore = KeyStore.getInstance("JKS");
        InputStream truststorex = new FileInputStream("C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1TrustStore");
        truststore.load(truststorex, "wasp123".toCharArray());
        TrustManager[] tm;
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(truststore);
        tm = tmf.getTrustManagers();
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(kmf.getKeyManagers(), tm, null);
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        // Open a secure connection.
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setSSLSocketFactory(sockFact);
        con.setHostnameVerifier(hv);
        // Set up the connection properties
        con.setRequestProperty("Connection", "close");
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setUseCaches(false);
        con.setConnectTimeout(10000);
        con.setReadTimeout(10000);
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        con.setRequestProperty("Content-Length", Integer.toString(requestData.length()));

        // Send the request
        OutputStream outputStream = con.getOutputStream();
        outputStream.write(requestData.getBytes("UTF-8"));
        outputStream.close();

        // Check for errors
        int responseCode = con.getResponseCode();
        InputStream inputStream;
        if (responseCode == HttpURLConnection.HTTP_OK) {
            inputStream = con.getInputStream();
        } else {
            inputStream = con.getErrorStream();
        }
        System.out.println(inputStream);
        inputStream.close();            
        InputStreamReader isr = new InputStreamReader(con.getInputStream());
        BufferedReader in = new BufferedReader(isr);
        StringBuilder out = new StringBuilder();
        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            out.append(inputLine.replace("<![CDATA[", "").replace("]]>", "").replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""));
        }
        in.close();
        String result = out.toString();
        System.out.println(result);
        strResponse = result;
    } catch (Exception ex) {
        strResponse = "Connection Error " + ex;
        System.out.println(ex);
    }
    return strResponse;
}

The debug shows;

*AWT-EventQueue-0, READ: TLSv1 Handshake, length = 4
*** ServerHelloDone
[read] MD5 and SHA1 hashes:  len = 4
0000: 0E 00 00 00                                        ....
*** Certificate chain
***
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
[write] MD5 and SHA1 hashes:  len = 269
0000: 0B 00 00 03 00 00 00 10   00 01 02 01 00 A3 CE 04  ................
0010: FD F7 31 F4 CD 0E C5 F3   44 B9 BA 55 0E FE 1F 53  ..1.....D..U...S
0020: A7 11 55 02 DF 61 1E 55   A8 4E DB FF E9 EA E1 95  ..U..a.U.N......
0030: 7A 2C 86 4D 64 37 37 19   8F 5C AF 2D FF 31 AD 2E  z,.Md77..\.-.1..
0040: B9 62 00 6D 89 DC CB 3E   66 1E 3B 22 06 04 89 CE  .b.m...>f.;"....
0050: 52 99 73 8A FC FD 81 03   32 86 26 0B 3C 90 D6 85  R.s.....2.&.<...
0060: 03 71 47 0E C7 FE C6 25   DA DD 8D 5F D7 A0 A1 15  .qG....%..._....
0070: 1E 4C C4 17 ED 62 B5 E7   1E AF A1 4F 70 0B AF 89  .L...b.....Op...
0080: 72 02 62 DC 0F 8C C7 9C   D5 D2 32 35 08 4C 4E 2E  r.b.......25.LN.
0090: 8C 9A F8 4B 1F 41 3D F0   E8 B9 2A 48 13 59 44 D7  ...K.A=...*H.YD.
00A0: 8F A0 FE DC 3E 72 4F F6   FE 18 BF B9 6E 0B 8E 13  ....>rO.....n...
00B0: 21 12 A5 54 D0 43 EC BD   D2 37 91 7E DD BA 86 E3  !..T.C...7......
00C0: F8 67 4F F5 61 19 5B 15   71 7F 32 69 02 7E CC 2E  .gO.a.[.q.2i....
00D0: 04 A2 9D 7F 55 8C 46 49   DC 2F E1 E3 82 D0 92 BC  ....U.FI./......
00E0: 66 2A 1C AE 6A 9C C2 89   9D FF 23 75 E3 92 00 94  f*..j.....#u....
00F0: 2B 3A 03 A0 B6 3B 49 CA   09 8F 13 7B 3E C5 07 BA  +:...;I.....>...
0100: 23 FD CB 86 99 C7 01 75   93 7E B6 5F 14           #......u..._.
AWT-EventQueue-0, WRITE: TLSv1 Handshake, length = 269
[Raw write]: length = 274
0000: 16 03 01 01 0D 0B 00 00   03 00 00 00 10 00 01 02  ................
0010: 01 00 A3 CE 04 FD F7 31   F4 CD 0E C5 F3 44 B9 BA  .......1.....D..
0020: 55 0E FE 1F 53 A7 11 55   02 DF 61 1E 55 A8 4E DB  U...S..U..a.U.N.
0030: FF E9 EA E1 95 7A 2C 86   4D 64 37 37 19 8F 5C AF  .....z,.Md77..\.
0040: 2D FF 31 AD 2E B9 62 00   6D 89 DC CB 3E 66 1E 3B  -.1...b.m...>f.;
0050: 22 06 04 89 CE 52 99 73   8A FC FD 81 03 32 86 26  "....R.s.....2.&
0060: 0B 3C 90 D6 85 03 71 47   0E C7 FE C6 25 DA DD 8D  .<....qG....%...
0070: 5F D7 A0 A1 15 1E 4C C4   17 ED 62 B5 E7 1E AF A1  _.....L...b.....
0080: 4F 70 0B AF 89 72 02 62   DC 0F 8C C7 9C D5 D2 32  Op...r.b.......2
0090: 35 08 4C 4E 2E 8C 9A F8   4B 1F 41 3D F0 E8 B9 2A  5.LN....K.A=...*
00A0: 48 13 59 44 D7 8F A0 FE   DC 3E 72 4F F6 FE 18 BF  H.YD.....>rO....
00B0: B9 6E 0B 8E 13 21 12 A5   54 D0 43 EC BD D2 37 91  .n...!..T.C...7.
00C0: 7E DD BA 86 E3 F8 67 4F   F5 61 19 5B 15 71 7F 32  ......gO.a.[.q.2
00D0: 69 02 7E CC 2E 04 A2 9D   7F 55 8C 46 49 DC 2F E1  i........U.FI./.
00E0: E3 82 D0 92 BC 66 2A 1C   AE 6A 9C C2 89 9D FF 23  .....f*..j.....#
00F0: 75 E3 92 00 94 2B 3A 03   A0 B6 3B 49 CA 09 8F 13  u....+:...;I....
0100: 7B 3E C5 07 BA 23 FD CB   86 99 C7 01 75 93 7E B6  .>...#......u...
0110: 5F 14                                              _.
SESSION KEYGEN:
PreMaster Secret:
0000: 03 01 87 D8 D9 C4 7A 0E   70 71 79 EB 45 13 D4 3C  ......z.pqy.E..<
0010: 6B 6C 39 46 B3 9A 74 1C   F1 E1 C5 40 D0 9E 31 8A  kl9F..t....@..1.
0020: 2E 62 7D 30 C2 DF 52 20   57 B3 8E 3E 49 93 39 58  .b.0..R W..>I.9X
CONNECTION KEYGEN:
Client Nonce:
0000: 53 AA 8D 7D AE 5C 8B 32   20 6A 21 7B B0 27 14 D8  S....\.2 j!..'..
0010: 35 04 E3 1C 5B 0C 42 BA   9A 5D 57 4B D1 5B 7B B3  5...[.B..]WK.[..
Server Nonce:
0000: 0B 61 3E 18 09 7C 4F 9A   77 E9 DD D5 67 D2 57 4D  .a>...O.w...g.WM
0010: 46 86 89 BA 73 44 95 1B   EB B2 BF E7 87 71 E4 15  F...sD.......q..
Master Secret:
0000: 75 69 ED F5 6F B0 C1 91   98 6E BF B0 07 0E 55 5F  ui..o....n....U_
0010: 35 B6 84 1E 80 86 98 85   5E EB C9 C3 26 D0 2F 67  5.......^...&./g
0020: 38 68 D9 9E ED 5F AD CC   1F D0 53 99 0A BC 66 FC  8h..._....S...f.
Client MAC write Secret:
0000: EF DB 37 8A 29 EC 22 DB   CB EC BB 82 0C 02 2A 64  ..7.).".......*d
0010: 00 82 6C 73                                        ..ls
Server MAC write Secret:
0000: 9D A3 A7 F7 3C DC 7C F0   57 69 93 D2 03 ED 65 6E  ....<...Wi....en
0010: 93 B9 2B 09                                        ..+.
Client write key:
0000: EA C1 F1 E6 08 EC C9 D2   71 9D F7 CA D2 9F 27 FC  ........q.....'.
Server write key:
0000: 2D 4D AD 16 80 F2 F4 AB   0B FD 8C 34 B7 55 98 35  -M.........4.U.5
... no IV used for this cipher
AWT-EventQueue-0, WRITE: TLSv1 Change Cipher Spec, length = 1
[Raw write]: length = 6
0000: 14 03 01 00 01 01                                  ......
*** Finished
verify_data:  { 150, 115, 119, 114, 39, 77, 15, 131, 88, 3, 74, 11 }
***
[write] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C 96 73 77 72   27 4D 0F 83 58 03 4A 0B  .....swr'M..X.J.
Padded plaintext before ENCRYPTION:  len = 36
0000: 14 00 00 0C 96 73 77 72   27 4D 0F 83 58 03 4A 0B  .....swr'M..X.J.
0010: 65 5E 4B 60 1B 76 B9 8A   A1 99 5B E8 D9 DE 4E 99  e^K`.v....[...N.
0020: 37 C3 00 0D                                        7...
AWT-EventQueue-0, WRITE: TLSv1 Handshake, length = 36
[Raw write]: length = 41
0000: 16 03 01 00 24 B9 AF 28   41 17 44 C0 9E DD 6B 03  ....$..(A.D...k.
0010: 92 55 85 6E F8 8E 9A F1   42 67 79 7F 19 8E DB 28  .U.n....Bgy....(
0020: CB A7 32 DA A3 06 A7 81   07                       ..2......
[Raw read]: length = 5
0000: 15 03 01 00 02                                     .....
[Raw read]: length = 2
0000: 02 28                                              .(
AWT-EventQueue-0, READ: TLSv1 Alert, length = 2
AWT-EventQueue-0, RECV TLSv1 ALERT:  fatal, handshake_failure
%% Invalidated:  [Session-1, SSL_RSA_WITH_RC4_128_SHA]
AWT-EventQueue-0, called closeSocket()
AWT-EventQueue-0, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
AWT-EventQueue-0, called close()
AWT-EventQueue-0, called closeInternal(true)
Received fatal alert: handshake_failure*
Njeru
  • 11
  • 3
  • 2
    I'm suspicious of the fact that you use the same key store for both your keystore and the truststore. I'm not sure that it wont work, but I've never seen that before. Here's some working code for this...probably more than you need, but it should get you going:http://chariotsolutions.com/blog/post/https-with-client-certificates-on/ – GreyBeardedGeek Jun 21 '14 at 11:59
  • 1
    Are there any intermediate CA certificates involved? – Bruno Jun 23 '14 at 00:29
  • Hi @Bruno. The server provides 3 CA certificates that I load to truststore, and a client server that the server uses to authenticate the client who is me. – Njeru Jun 23 '14 at 05:32
  • @GreyBeardedGeek I will separate them and retry. But is there a reason it cannot work? – Njeru Jun 23 '14 at 05:34
  • @GreyBeardedGeek I did create a truststore and loaded the CA certificates into it but same result. I created a truststore and loaded the CA certificates into it. System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1TrustStore"); System.setProperty("javax.net.ssl.trustStorePassword", "x123"); – Njeru Jun 23 '14 at 06:18
  • @Bruno The problem now is during handshake, after the server hallo and I acknowledge its certificate, my client is to pass a key + certificate. From the trace I am successfully passing the key but the certificate shows 0 bytes. So I get the javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure. From the keystore, I can see 2 entries a PrivateKeyEntry and the certificate. Any idea why the client is not sharing the certificate? – Njeru Jun 24 '14 at 15:25
  • "*my client is to pass a key + certificate*" that doesn't make sense, private keys are never exchanged. Check [this question](http://stackoverflow.com/q/9299133/372643) perhaps. – Bruno Jun 24 '14 at 15:29
  • @Bruno I followed the question in the link and I associated the certificate but still I am sending 0 bytes during cert exchange. – Njeru Jun 25 '14 at 08:45
  • Check the `CertificateRequest` message you get just before the `ServerHelloDone` message to see its `certification_authorities` list, then check whether your client-cert chain can go back to one of its issuers. – Bruno Jun 25 '14 at 11:47

2 Answers2

0

My code is accepting their certificates

Meaning the server certificate.

sending the key

Your code is not sending any key. SSL doesn't send keys.

but not the server certificate.

You received the server certificate. You're the client. You don't send the server its own certificate.

If you mean you're not sending the client certificate, that will probably be because the server doesn't trust it. The server sends a CertificateRequest naming the accepted issuers, and the client can only send a certificate signed directly or indirectly by one of those issuers. If it doesn't have one it sends nothing. In other words a problem at the server end.

You need to sort out the keystore/truststore confusion. You should use separate files. The keystore is for the key and certificate; the truststore is for trusted certificates, in this case the exported server certificates. Don't use a single file for both. They have quite distinct purposes and distinct security regimes around them.

You haven't needed to set the java.protocol.handler.pkgs property for SSL since 2004.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I created a truststore and loaded the CA certificates into it. System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre7\\bin\\testserver1TrustStore"); System.setProperty("javax.net.ssl.trustStorePassword", "x123"); But still same result. – Njeru Jun 23 '14 at 06:17
  • The real problem is during handshake my code passes no certificate i.e 0 bytes. So it fails. When I list my keystore I get 2 entries a PrivateKeyEntry and the certificate. Any idea why 0 bytes? – Njeru Jun 24 '14 at 09:08
  • I've already told you. Your client sent a zero length certificate chain because it didn't have any certificates signed by issuers acceptable to the server. – user207421 Jun 25 '14 at 09:41
0

How I solved it.

Removed all the certs from my keytool.

Command Example : keytool -delete -alias myCert -keystore mystore.jks

I converted the cert response from server to bas64 DER and copied them into one file a .PEM, and I uploaded the .PEM into my keytool:

Command Example : keytool -importcert -keystore keystore.jks -alias mystore -file my.pem

Then I loaded the keystore:

KeyStore myStore = KeyStore.getInstance("JKS");
InputStream keyInputx = new FileInputStream("C:\\myStore.jks");
myStore.load(keyInputx, "xxx".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyInputx.close();
/*Enumeration enumeration = myStore.aliases();
 while (enumeration.hasMoreElements()) {
     String alias = (String) enumeration.nextElement();
     System.out.println("alias name: " + alias);
     Certificate certificate = myStore.getCertificate(alias);
     System.out.println(certificate.toString());
 }*/
keyManagerFactory.init(myStore, "xxx".toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
SSLSocketFactory sockFact = context.getSocketFactory();
Njeru
  • 11
  • 3
  • How you solved it was to import the signed CSR under the same alias as the original private key it was generated from. – user207421 Jun 30 '14 at 20:07