2

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?

user207421
  • 305,947
  • 44
  • 307
  • 483
Iulian
  • 319
  • 4
  • 13
  • The alias has nothing to do with the target domain whatsoever. You don't need multpille copies of the same certificate. – user207421 Jun 16 '15 at 22:54

1 Answers1

3

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.)

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • Here is an additional question. If Cert Authorities: is there anyway you can pass a client certificate? – Iulian Jun 17 '15 at 13:43
  • Yes, that's what I said in the last sentence: it will send the first certificate it finds (which shouldn't be a problem if you only have one in the keystore). The server would still need to send that certificate request, and whether or not the cert will be accepted is up to the server implementation and configuration. It would certainly need a way to verify that certificate one way or another. – Bruno Jun 17 '15 at 14:17
  • Bruno, one more question: Is there complete necessary for the client to use/provide the private key after the server replies CertificateRequest? – Iulian Jun 18 '15 at 14:12
  • The client does provide the private key to the server, but it does need to use it to complete the handshake (to sign the content of the `Certificate Verify` message). Without that, there would be no authentication (certificates are rather public otherwise). – Bruno Jun 18 '15 at 14:36
  • 1
    @Bruno You mean the client does *not* provide the private key to the server. – user207421 Oct 17 '16 at 03:58
  • @EJP Of course, sorry about the typo. Maybe I should just re-write that comment altogether (since we can't edit them). – Bruno Oct 17 '16 at 08:46