javatruststorejsse

JDK bundled TrustManager


I would like to get a TrustManager instance loaded with JDK's bundled trust material (meaning the material which in later versions of the JDK live in lib/security/cacerts file). Ideally the solution should work on JDK8 and later.

I must admit I find this - seemingly very simple request - to be very complex. Which leads me to doubt if I'm going about this the right way.

Here are the snags I see:

I really don't want to deal with all these differences between JDKs. And I believe I shouldn't. I believe my request is reasonable. Someone might have already solved it or the JDK provides a way to get this that I've overlooked?

Thank you for any pointers or help, you may provide.


Solution

  • Taking a step back. The task is to get hold of the JDK's bundled curated set of CA certs. However, the underlying goal is really for the application to be using just some kind of curated set of CA certs, similar to what a browser does. It doesn't necessarily need to be the set defined by the JDK. By "curated" we mean that there is a thoughtful ongoing process as to which CA certs is included in the set and that this process is managed by a trustworthy organization.

    Getting hold of the JDK's unmodified cacerts file is near impossible in Java. This is what the JDK 21 documentation has to say about the cacerts file:

    cacerts Certificates File

    A certificates file named cacerts resides in the security properties directory:

       Linux and macOS: JAVA_HOME/lib/security
    
       Windows: JAVA_HOME\lib\security
    

    The cacerts file represents a system-wide keystore with CA certificates. System administrators can configure and manage that file with the keytool command by specifying jks as the keystore type. The cacerts keystore file ships with a default set of root CA certificates. For Linux, macOS, and Windows, you can list the default certificates with the following command:

       keytool -list -cacerts
    

    The initial password of the cacerts keystore file is changeit. System administrators should change that password and the default access permission of that file upon installing the SDK.

    Note:

    It is important to verify your cacerts file. Because you trust the CAs in the cacerts file as entities for signing and issuing certificates to other entities, you must manage the cacerts file carefully. The cacerts file should contain only certificates of the CAs you trust. It is your responsibility to verify the trusted root CA certificates bundled in the cacerts file and make your own trust decisions.

    To remove an untrusted CA certificate from the cacerts file, use the -delete option of the keytool command. You can find the cacerts file in the JDK's $JAVA_HOME/lib/security directory. Contact your system administrator if you don't have permission to edit this file.

    This seems like bad advice: Changing the content of the JDK installation shouldn't be done. It should be treated as immutable, IMHO. Also, I think the "changeit" password comment is no longer true.

    Bottom line is that - if someone took this advice - that a Java application cannot be sure what cacerts file it uses or if it can even read the certs in the file.

    Of course, in these more modern days with containers and all, I can be pretty certain that my application runs atop of an unmodified JDK/JRE installation and I can therefore confidently process the cacerts.

    But going forward I would hope that the JDK would provide a way to get hold of the unmodified bundled CA set. I would also hope that they would stop encouraging making changes to a JDK/JRE installation tree ... post installation. Even if nobody cares anymore.

    Finally, another option for an application would be to bundle someone else's curated set of CA certs, for example Mozilla CA certs set.