Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8224891

The CACERTS keystore type

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Withdrawn
    • Icon: P3 P3
    • None
    • security-libs
    • None
    • binary
    • minimal
    • Hide
      The cacerts file is still located in the same directory with the same name, and is still loadable with `KeyStore.getInstance("JKS").load(fileStream, null or anything)` just like today. Read more in the compatibility description on the specification.
      Show
      The cacerts file is still located in the same directory with the same name, and is still loadable with `KeyStore.getInstance("JKS").load(fileStream, null or anything)` just like today. Read more in the compatibility description on the specification.
    • File or wire format
    • Implementation

      Summary

      Create a new CACERTS KeyStore type and file format.

      Problem

      JDK stores out-of-box root CA certificates in lib/security/cacerts and it's using a proprietary keystore format JKS.

      1. It's not standard.
      2. It requires a password to check for integrity. This password must be publicized and therefore provides no security protection. On the other hand, including a hardcoded password is not a good security practice.
      3. People might change the password and this could break existing applications that uses the hardcoded password.
      4. We've already changed the default keystore type from JKS to PKCS12 in JDK 9 and we are warning people to migrate from JKS in keytool warnings now.
      5. There are almost 100 certificates in this file and loading it spends quite some time

      Solution

      Hardcode all builtin CA certificates into OpenJDK code, and migrate the cacerts file into an ASCII file that allows users to add their own CA certs or shadow builtin ones. The new keystore type will be named "CACERTS".

      Specification

      Builtin CA certs

      All (93) CA certificates that are currently inside the lib/security/cacerts file are moved into an internal class inside the java.base module. This class will be generated at build time using the same certificate files in make/data/cacerts.

      The CACERTS file format

      # CACERTS
      # DO NOT REMOVE THE LINE ABOVE
      #
      # Remove a CA cert by its alias
      @remove-alias: <a CA alias name>
      #
      # Remove all CA certs
      @remove-all
      #
      # Add a new CA cert with
      @alias: newaliasname
      -----BEGIN CERTIFICATE-----
      .....
      -----END CERTIFICATE-----
      1. The first line must be # CACERTS
      2. The @remove-alias directive can be used to remove a CA cert by its alias. Users can call keytool -cacerts -list to find out the aliases for all builtin CA certificates.
      3. The @remove-all directive can be used to remove all CA certs.
      4. The @alias directive following a BASE64 encoded X.509 certificate can be used to add a new CA cert with this alias.

      Note:

      1. This file format will be used by the new CACERTS keystore type below.
      2. When parsing starts, all hardcoded builtin CA certs are loaded (the current list).
      3. All directives are processed in their appearance order in the file. For example: Users can add @remove-all as the first directive in a CACERTS file to remove all builtin CA certs and then add their own ones. Or, they can add a @remove-alias: verisignclass2g2ca [jdk] directive to remove this single builtin CA cert and then (optionally) add their own ones. Please note that if @remove-all is on the last time, it will empty the whole list including newly added CA certs.
      4. If a BASE64 encoded X.509 certificate appears without a leading @alias directive, its SHA-256 fingerprint will be used as its alias.
      5. Unknown directives (other lines starting with @) will be treated as an error.
      6. All other lines are ignored (as comments).
      7. The out-of-box lib/security/cacerts will be all comment lines except for the first line. All existing (93) cacerts have been hardcoded inside OpenJDK using the same aliases as before.

      The CACERTS keystore type

      1. When using KeyStore.getInstance(File, password) to load a file starting with the # CACERTS line, it will be probed as a CACERTS keystore.
      2. The store password is ignored in KeyStore.getInstance(File, password) and KeyStore.load(InputStream, password).
      3. When calling KeyStore.load(null, password), the system-default CACERTS keystore at lib/security/cacerts is loaded.
      4. The creation time of a certificate inside a CACERTS keystore is not defined but it will not be null.
      5. Calling KeyStore.setEntry with a KeyEntry or KeyStore.setKeyEntry on a CACERTS keystore is allowed and the new entry is visible in the keystore object (but see below).
      6. Calling KeyStore.store(OutputStream, password) will write out a CACERTS keystore to the output stream. All key entries are ignored. The password is ignored. Loading a keystore from a CACERTS file and storing it back to the same file will not retain the comments or the order of directives. The output stream cannot be null (i.e. one cannot write into the system-default CACERTS keystore by using a null output stream).

      This new keystore type name will be added into the "Java Security Standard Algorithm Names" and the "JDK Providers Documentation" in the Java SE Security Guide.

      Compatibility with existing keystore types

      1. A CACERTS file can be loaded as a JKS or PKCS12 keystore, and the load password is ignored. When KeyStore.store is called on such a keystore, a CACERTS file will be written, and key entries will be ignored. This makes sure the current programs that is using "JKS" to load/store the cacerts file can work with the new file format.
      2. One can load a JKS keystore with the CACERTS store type. This makes sure that if a user has replaced the system-default cacerts file with a JKS keystore, it can still be loaded as a CACERTS keystore. When calling KeyStore.store on such a keystore, a JKS keystore will be written, if any key entry was added into the KeyStore object it will be stored, the store password will be used.
      3. The CACERTS KeyStore type and the CACERTS file format can be separated. We can forsee in the future that the system-default root CA certs list to be stored in a different way but they can still be loaded with KeyStore.getInstance("CACERTS").load(null, null).

            weijun Weijun Wang
            vinnie Vincent Ryan
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: