0
votes

I have a customer who replaced the keystore and truststore of our product components. After replacement the components can't communicate with each other (2 way SSL).

On SSL logs I see:
http-nio-8100-exec-2, fatal error: 42: null cert chain javax.net.ssl.SSLHandshakeException: null cert chain %% Invalidated: [Session-6, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256] http-nio-8100-exec-2, SEND TLSv1.2 ALERT: fatal, description = bad_certificate http-nio-8100-exec-2, WRITE: TLSv1.2 Alert, length = 2 http-nio-8100-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain

They have configured the same keystore and truststore files on both sides. I've opened their keystore and truststore and this is how they are built:
keystore
entry1 - server
cert[1] MD5: X
cert[2] MD5: Y
cert[3] MD5: Z

truststore
entry1 - root
cert[1] MD5: Z
entry2 - intermediate
cert[1] MD5: Y

It seems to me that the fact that cert[1] in the keystore (with MD5 X) is missing from the truststore is problematic.

Am I right?

Can you see any other problem with the way their keystore and truststore was built?

2
Do you components communicate both ways or is or is it a client-server architecture? Is it 1-way or 2-way SSL? - RZet
2 way. I will update the question as well. - danieln
If it's 2-way SSL, you should have a keystore and truststore on either side of the fence, which you haven't specified in your question. Your also aren't clear which way it fails. You need to be more specific in your post. - RZet
Thanks. I've added to the question: They have configured the same keystore and truststore files on both sides. Does it still matter which way it fails? - danieln
The direction shouldn't matter in that case. Is cert[1] in the keystore a self-signed certificate? - RZet

2 Answers

1
votes

It looks like your problem is related to some missing certificates either in your keystore and/or truststore.

Generally speaking, when the client sends a request to the server, the server presents its certificate chain which must include the server's certificate as the first entry followed by its issuer and other issuers. Each following certificate must directly certify the one preceding it unless it is present in the truststore on the client-side.

You need to check whether your cert[1] in keystore is a self-signed certificate. You can achieve this in the following way:

For .jks Java keystore type:

keytool -list -v -keystore [keystore-file-name].jks

-For #PKCS12 keystore type:

keytool -list -keystore [keystore-file-name].p12 -storetype PKCS12 -v

When the certificate is printed, check the 'Issuer' attribute.

If it matches the 'Owner' attribute, it means it's a self-signed certificate and you need to add the 'cert[1]' into the truststore.

If they don't match, try one of the following alternatives:

  • Generate a new 'cert[1]' signed by either 'Y' or 'Z' and add it into the keystore or replace the existing one. The decision whether to replace it or add depends how your code reads the certificate. A replacement might be a better option.
  • Add the current 'Issuer' of 'cert[1]' of the keystore into the truststore.

If the certificate of the 'Issuer' of 'cert[1' in the keystore is already present in the truststore, I would've expected the SSL handshake to be successful.

Here is how you add an issuer to a truststore:

1) Get hold of the Public Certificate of the issuer, which is stored in .cer file. If the issuer is self-generated and you've got access to its keystore, the certificate an be exported from there using the following command:

keytool -export -keystore [issuer-keystore].jks -alias [alias]-file [output-file-name].cer

2) Import the .cer file into the truststore:

keytool -importcert -file [output-file-name].cer -keystore [truststore-file-name].jks -alias [alias]
0
votes

Am I right?

No. As long as the truststore contains one of the certificates in the keystore's certificate chain, it should trust the certificate in the KeyStore.