Java client certificates and keystores

3.5k Views Asked by At

we are trying to build a MUTUAL/2WAY authentication mechanism.

Because we hit two different hosts, we have the same client certificate stored in the client keystore container under two different aliases (please note the same fingerprint):

root@perf-golem-4:/opt/golem# keytool -list -keystore ./client.keystore -storepass ________

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

i.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 28:94:45:A1:78:C0:BD:D6:82:7E:09:66:15:11:8D:A5:56:0B:99:39
r.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 28:94:45:A1:78:C0:BD:D6:82:7E:09:66:15:11:8D:A5:56:0B:99:39

Now, under the trusted container we have the target domains certificates (please note how the fingerprint is different between them and also compared to the keystore above):

root@perf-golem-4:/opt/golem# keytool -list -keystore ./trusted.keystore -storepass _______

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

i.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 73:F5:96:68:89:56:5E:50:9C:06:69:67:AC:8E:18:D2:D9:C1:33:71
r.domain.io, Jun 16, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): 12:93:C8:41:3F:68:22:8F:40:F8:3C:B9:B6:C4:90:C0:60:49:D0:50

My understanding is that if you have to store a certificate with an alias matching the target domain name (in our case i.domain.io or r.domain.io) so java can provide the associated certificate as a client certificate when you are attempting a SSL connection to that domain e.g. https://r.domain.io

We are launching our app like this:

java    -Djavax.net.debug=all \
        -Djavax.net.ssl.keyStore=/opt/golem/client.keystore \
        -Djavax.net.ssl.keyStorePassword=_____ \
        -Djavax.net.ssl.trustStore=/opt/golem/trusted.keystore \
        -Djavax.net.ssl.trustStorePassword=_____ \

Our problem is that no client certificate is being presented, or used from the client side so, the big question is does java provide the client certificate associated with an alias that matches target domain name (or subject line in the target SSL cert) or the name of the certificate should be mangled from the code?

1

There are 1 best solutions below

6
On BEST ANSWER

My understanding is that if you have to store a certificate with an alias matching the target domain name (in our case i.domain.io or r.domain.io) so java can provide the associated certificate as a client certificate when you are attempting a SSL connection to that domain e.g. https://r.domain.io

That's not the case at all.

Matching is based on the certificate_authorities list sent by the server in its TLS CertificateRequest message (the issuers), and on the type of key (e.g. RSA or DSA). Some imperfect matches can be chosen if the attributes are not quite as expected (see this answer), but you'd at least want to have your client certificate issued by a CA the server advertises for (this is generally done automatically on the server side when you configure the CA certificates it's willing to accept, unless you explicitly change the configuration there).

If intermediate certificates are required, you'll certainly want to make sure you've imported the full chain.

Essentially, there is no point having twice the same certificate in your keystore.

(You can try to force a specific alias by extending your own X509KeyManager, but that's not sufficient; in particular, that's not going to make the server request it nor make the chain valid.)

You need to make sure that the server is configured to request a certificate. This can sometimes be done via renegotiation, so the CertificateRequest TLS message might not necessarily be visible using Wireshark. However, you should be able to see it from the client side using -Djavax.net.debug=ssl (or all): the official documentation for Debugging SSL/TLS Connections has an example if you search for CertificateRequest on the page.

Then, you need to make sure your certificate (or the top of the chain on the client end, if there are intermediate certs) was issued by one of the CAs that is advertised in that CertificateRequest message (the Issuer DN must match).

(If the certificate authorities list in CertificateRequest is empty, but the CertificateRequest message is still sent, the client will send the first certificate it finds in its keystore by default. That sort of scenario is atypical, since it requires custom configuration on the server side in general.)