Search code examples
javassljceopenjdk-11

How is is possible that Java 11 validates a certificate whom intermediate certificate isn't avalaible in cacerts?


I don't have to fix something that doesn't work, but I try to understand why something works, because I think it should not work.

I'm using OpenJDK11 / Ubuntu 16.04. I make an HTTPS call. The SSL handshake succeeds.

The cert chain contains 3 certs:

  • API certificate of course. Issued by an intermediate CA (issuer = CN = DigiCert TLS RSA SHA256 2020 CA1,O = DigiCert Inc,C = US)
  • Intermediate CA certificate. Issued by a root CA (issuer = CN = DigiCert Global Root CA,OU = www.digicert.com,O = DigiCert Inc,C = US)
  • Root certificate

The second certificate is not available in the cacert keystore in use (default keystore under lib/security folder). This sounds quite normal as the cert was issued in April 2021, while the JRE was released on January 2021 (openjdk version "11.0.10" 2021-01-19)

Why can this handshake succeed? In my mind, as Java doesn't know the second certificate, it can not validate the API certificate.


Solution

  • In order to validate the server certificate during the ssl handhshake phase, the http client needs the certificate which was used to sign the server certificate (the intermediate certificate), and the certificate which was used to sign the intermediate certificate (root certificate).

    All these certificates constitute what is known as "the chain of certification". There is usually one intermediate certificate, sometimes there is no intermediate certificate (server cert signed directly by the root certificate), or you could have many intermediate certificates.

    JCE/JSE needs all these certificates for validating the server identity. If one certificate is missing (generaly the root certificate), or perempted, or invalid, or under some circumstances due to network failures or bad server setup, java throws a SSLHandshakeException.

    Java looks for the root certificate in his trusted store (according to the JRE setup : there are defaults, they can be overrided by differents ways) The server certificate is sended by the server.

    I thought that the intermediate certificate has to be present also in the java trusted store. This was a mistake. In fact, the intermediate certificate is sended by the server also.

    i hadn't a SSLHandhakeException while the intermediate certificate was not present in the java trust store, so i didn't understood. After speaking here, and writing some lines of java to read what is sended by the server, i understand now that the intermediate certificate is sended by the server.

    So, you don't need to have the intermediate(s) certificate(s) in java trust store for the ssl handhsake to succeed.