Why doesn't Java send a client certificate during SSL confirmation?

I am trying to connect to a secure web service.

I did not receive a handshake even though the keystore and trust store were installed correctly.

After several days of disappointment, an endless Google search and finding out all around, I found out that the only problem was that Java decided not to send the client certificate to the server during the handshake.

In particular:

  • The server requested a client certificate (CN = RootCA) - that is, "give me a certificate signed by the root CA"
  • Java looked into the keystore and only found my client certificate, signed by "SubCA", which, in turn, is issued by "RootCA". He did not bother to look into the trust network ... duh OK I think
  • Unfortunately, when I tried to add the "SubCA" certificate to the keystore, that didn't help at all. I checked if certificates are uploaded to the keystore. They do, but KeyManager ignores all certificates except the client.
  • All of the above leads to the fact that java decides that it does not have certificates that satisfy the server’s request and sends nothing ... tadaaa handshake failure: - (

My questions:

  • Is it possible that I added the “SubCA” certificate to the key store so that it “broke the certificate chain” or something that KeyManager only downloads the client certificate and ignores the rest? (Chrome and openssl will handle this so why can't they be java? - note that the SubCA certificate is always presented separately as a trusted authority, so Chrome seems to correctly package it along with the client certificate during a handshake)
  • Is this the official “server side configuration problem”? The server is a third party. I expect the server to request a certificate signed by SubCA since they provided us. I suspect that the fact that this works in Chrome and openssl is that they are "less restrictive" and java just "by the book" does not work.

I managed to put together a dirty workaround for this, but I am not very happy with it, so I will be glad if anyone can clarify this for me.

+57
java certificate ssl ca
Feb 15 '12 at 18:30
source share
3 answers

Perhaps you could import the CA intermediate certificate into the keystore without associating it with the record in which you have the client certificate and its private key. You should see this using keytool -v -list -keystore store.jks . If you receive only one certificate for an alias record, they are not together.

You will need to import your certificate and its chain together into a key store alias that has your private key.

To find out which key alias the private key stores, use keytool -list -keystore store.jks (here I take the JKS store type here). This will tell you something like the following:

 Your keystore contains 1 entry myalias, Feb 15, 2012, PrivateKeyEntry, Certificate fingerprint (MD5): xxxxxxxx 

Here is the alias myalias . If you use -v in addition to this, you should see Alias Name: myalias .

If you do not have it separately, export the client certificate from the keystore:

 keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias 

This will give you the PEM file.

Using a text editor (or cat ), prepare a file (call bundle.pem ) with this client certificate and an intermediate CA certificate (and possibly the root CA certificate itself, if you want) so that the client certificate is at the beginning and its certificate the issuer is slightly lower.

It should look like this:

 -----BEGIN CERTIFICATE----- MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa .... -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV .... -----END CERTIFICATE----- 

Now import this package back into the alias where your private key is located:

 keytool -importcert -keystore store.jks -alias myalias -file bundle.pem 
+83
Feb 15 '12 at 20:21
source share

As an addition here, you can use%> openssl s_client -connect host.example.com-00-0043 and look at the dump and verify that the entire main certificate is valid for the client. You are looking for this at the bottom of the output. Check return code: 0 (ok)

If you add -showcerts, it resets all the keychain information that was sent along with the host certificate, and this is what you uploaded to your keychain.

+5
Jul 23 '14 at 0:02
source share

The fact is that when using a client certificate signed by an intermediate certificate, you must include the intermediate certificate in your list of users so that java can find it. Either alone or complete with a root edition of approx.

0
Feb 06 '19 at 6:59
source share



All Articles