OpenJDK Cookbook
上QQ阅读APP看书,第一时间看更新

Preparing CA certificates

Public-key cryptography is used widely on the Internet. When the web browser opens a secured website, it checks the server-side certificate against the website domain name. To perform such checks, all web browsers have a list of Certificate Authority (CA) certificates that may be used to sign server-side certificates of websites. Such checks may be disabled but they are a necessary part of secure web browsing, client banking, and so on.

When website access is used by a Java program (for example, to download a file from a secure site), programs such as the browser in the preceding example should check the site certificate. Such a check is usually performed by the underlying SSL API implementation, and with the browser, the list of CA certificates must be available to the OpenJDK runtime.

Such a list is stored in the openjdk_directory/jre/security/cacerts file in the Java KeyStore (JKS) format. In official OpenJDK 6 tarballs, the cacerts file contains no certificates. If runtime with such empty file is used to access a secured website, an obscure exception will be thrown.

The following code snippet will cause the exception with the root cause:

new URL("https://github.com/").openStream().close();
Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:...
        at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:120)
        at java.security.cert.PKIXBuilderParameters.<init>(PKIXBuilderParameters....
        at sun.security.validator.PKIXValidator.<init>(PKIXValidator.java:73)
        ... 47 more

Getting ready

To prevent such an exception, a proper cacerts file should be prepared. It may be used during the OpenJDK build or added to the jre/security directory later. The list of CA certificates should be obtained and converted to the JKS format. To download and convert the CA list, we will need a recent version of the Ubuntu (or similar Linux-based) operating system with cURL and keytool utilities installed. You will also need cat, awk, and csplit standard utilities; these should be already installed as part of the coreutils package.

How to do it...

The following steps will help us to prepare CA certificates:

  1. Install the cURL utility:
    sudo apt-get install curl
    
  2. Install the keytool utility as part of the prebuilt OpenJDK package:
    sudo apt-get install openjdk-7-jdk
    
  3. Download the CA list used by the Firefox web browser, preconverted in the PEM format from the cURL library website into the cacert.pem file:
    curl -L http://curl.haxx.se/ca/cacert.pem -o cacert.pem
    
  4. Split the cacert.pem file into multiple files with the cert_ prefix. Each file will contain a single CA certificate:
    cat cacert.pem | awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/{ print $0; }' > cacert-clean.pem
    csplit -k -f cert_ cacert-clean.pem "/-----BEGIN CERTIFICATE-----/" {*}
    
  5. Create a JKS keystore and load all CA certificates there using keytool:
    for CERT_FILE in cert_*; do
     ALIAS=$(basename ${CERT_FILE})
     echo yes | keytool -import -alias ${ALIAS} -keystore cacerts -storepass 'changeit' -file ${CERT_FILE} || :
    done
    
  6. Check the cacerts file's contents:
    keytool -list -keystore cacerts -storepass 'changeit'
    

Now the cacerts file is ready to use.

How it works...

A list of CA certificates used by the Firefox web browser is freely available as part of the open source security library from Mozilla called NSS. This list is available in text format at http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt. We have used the same file but preconverted it in to PEM format, which is available at the cURL website.

The keytool utility understands certificates in the PEM format, but it can only load certificates one-by-one, so the big PEM file is split beforehand. Also, the keytool utility has strict requirements from the PEM files: no text content is allowed before /-----BEGIN CERTIFICATE-----/ and after /-----END CERTIFICATE-----/ strings. The awk utility is used to strip unneeded prefixes and postfixes.

Then the csplit utility is used to split the file using /-----BEGIN CERTIFICATE-----/ separators.

Next, the split files are loaded into the keystore one by one. The keystore is created on the first certificate load.

The changeit password is used for this keystore, which may be quite an unsecure choice for the password. However, this does not matter for the cacerts file because the CA certificates contain only public keys and need not be hidden behind the password.

There's more...

Most of this recipe is not specific to the Ubuntu operating system; any Unix-like environment (for example, Cygwin on Windows) would suffice.

Bash scripts in this recipe can be replaced by any other scripting language such as Python or PowerShell.

Instead of the CA list from Firefox, any other set of CA certificates may be used. Some CA certificates may be removed, for example a particular CA certificate not trusted by the user, or some additional CA certificates may be added, for example inner corporate CA certificates to access a company's intranet resources.

See also