Hands-On Cryptography with Java—Appendices

Russell Bateman
August 2022

Table of contents

Appendices
Appendix 1: Make up for missing keystore vs. trust store focus
Appendix 2: Where do OSes keep their certificate authorites?
Appendix 3: Where do browsers keep their certificate authorities?
Appendix 4: Questions to answer

Appendix 1: Make up for missing keystore vs. trust store focus

The course mostly concentrated on how to interact with the keystore programmatically. Though interesting, this isn't what I need right now. Instead, this is me augmenting the course.

Java keystore

The Java keystore is a file—repository for one or more private keys, certificates containing public keys or just secret keys that can be used for various cryptological purposes. Each entity within is stored by an alias for easy look-up.

The best example of a server in Java-land would be Tomcat. Think of Tomcat in what follows.

A server that wants to use HTTPS presents its public key and certificate to clients. (Client authentication interests me not at all, so I will not elaborate here.)

There is no default Java keystore. For this reason the following must be set in the JVM:

  1. -Djavax.net.keyStore=filepath
  2. -Djavax.net.keyStorePassword=password
  3. -Djavax.net.keyStoreType=type

where:

  1. filepath is typically a file in the server's filesystem.
  2. password (default is "changeit")
  3. type is one of
    • JKS (Java Keystore)
    • PKCS12 (public-key cryptosystem, industry-standard)
    • PKCS11 (hardware interface)
    • Ignore these basically:
    • JCEKS (JCE Keystore, superset of JKS, uses 3DES)
    • BKS (Bouncy Castle Keystore)
    • DKS (Domain Keystore)
    • Windows-MY

Java trust store

This is a topic that got practically zero coverage in the course.

The Java trust store is also a file. It is the opposite of the keystore: while a keystore holds certificates that identify (a "first person"), the trust store holds certificates that identify others.

In Java, the trust store contents are used to determine whether to trust the third party being communicated with. This trust store is like the store operating systems and browsers ship with containing myriad certificates that can be found in legitimate certificate authority (CA) chains.

A server can get a public key and certificate from its own keystore to present to a client requesting its services.

The client then looks up the certificate in his own trust store.

Don't mistake the client for a human being: the client is software—a browser, curl or something else like NiFi InvokeHTTP over which the human user may not have "do it anyway" control (as he does in the browser or when running curl).

This means that the certificate presented by the server must either already exist in the client's trust store or a certificate authority (CA) in the chain of authority in the server's certificate.

When a server has a self-signed certificate—with no acceptable, publicly known and trusted authority (CA), the client will not be able (allowed) to trust the server, the client JVM will throw SSLHandshakeException and fail the connection.

Java has bundled with it a trust store named cacerts on the path ${JAVA_HOME}/lib/security 1 2 that contains default, trusted certificate authorities (CA) just as operating systems and browsers do. This is what the JVM gets by default when it runs. For instance, ...

russ@tirion /etc/ssl/certs/java $ keytool -list -cacerts
Enter keystore password: changeit
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 139 entries

debian:ac_raiz_fnmt-rcm.pem, Jan 3, 2021, trustedCertEntry,
Certificate fingerprint (SHA-256): EB:C5:57:0C:29:01:8C:4D:67:B1:AA:12:7B:AF:12:F7:03:B4:61:1E:BC:17:B7:DA:B5:57:38:94:17:9B:93:FA
...

If the server has a self-signed certificate, it is likely not among the 139 entries in cacerts nor does it include a chain among which is included a root certificate in those entries.

Therefore, the client will have to add—by hand—the server's self-signed certificate to his trust store (as an addition to the JVM's trust store, cacerts) in order to inform applications, such as a browser, curl or other software, that the server can be trusted.

Adding a self-signed certificate to Java's trust store is a "baling-wire and twine" method of getting authentic, commercial sign-off on the server's self-signed certificate for the client that adds it. It makes the server appear legitimate. For example, this is done:

$ keytool -import -trustcacerts -alias tomcat -file tomcat.crt -keystore cacerts

where tomcat.crt is the self-signed certificate (we're thinking about a Tomcat microservice here) and cacerts is the cacerts active in the client software's running JVM (${JAVA_HOME}/lib/security/cacerts) or supplied to that JVM by launching it with:

Notes

1 Before Java 9, this path was ${JAVA_HOME}/jre/lib/security.

2 cacerts is often not very mysterious. In a JDK, it's a shipping file on the path noted above, but formally installed as a JRE—for example, on Ubuntu and Mint—it ends up a very pedestrian location indeed, not far from where the operating system keeps its pile of trusted certificates:

root@tirion:# which java
/usr/bin/java
root@tirion:/home/russ# cd /usr/bin/
root@tirion:/usr/bin# ll -d java
lrwxrwxrwx 1 root root 22 Jan 28  2021 java -> /etc/alternatives/java*
root@tirion:/usr/bin# cd /etc/alternatives
root@tirion:/etc/alternatives# ll -d java
lrwxrwxrwx 1 root root 43 Jan 28  2021 java -> /usr/lib/jvm/java-11-openjdk-amd64/bin/java*
root@tirion:/etc/alternatives# cd /usr/lib/jvm/java-11-openjdk-amd64/
root@tirion:/usr/lib/jvm/java-11-openjdk-amd64# ll -d lib/security/cacerts
lrwxrwxrwx 1 root root 27 Jul 22 03:14 lib/security/cacerts -> /etc/ssl/certs/java/cacerts

Appendix 2: Where do OSes keep their certificate authorities (CA)?

As implied in the note just above, Linux keeps its list of trusted certificates on the path /etc/ssl/certs.

Appendix 3: Where do browsers keep their certificate authorities (CA)?

This is me more repeating details that the course discussed early on.

The major root certificate stores are Apple, Microsoft, Mozilla and Android (Google). When you visit a website, it presents a certificate that's signed by another certificate, which is signed by another certificate—and so on up a chain until you reach one of the certificates in the browser's store.

Each certificate store has its own requirements for a certificate authority (CA) to get added, however, they all require passing WebTrust for Certification Authorities, an audited assurance process for policies and procedures that verify identity, issue certificates, handle keys, etc.

Firefox is a good example of how to see the certificates it trusts. In Firefox 103, follow this path:

  1. Hamburger menu
  2. Settings
  3. Privacy & Security
  4. (scroll down to) Security
  5. (click) View Certificates...

A specific example

Once upon a time, you could bring up Chrome on google.com, launch Developer Tools, click the Security tab, then View Certificate to show details about google.com's certificate. There you would learn of...

  1. ...a site certificate for google.com which contained
  2. an intermediate certificate, Google Internet Authority G2, itself containing
  3. a root certificate, GeoTrust Global CA.

This is a simple example since many websites have more than one intermediate certificate in their chain before reaching a root certificate.

At that time, Chrome shipped with (at least) the root certificate that google.com and a lot of other websites' certificate chains would lead to.

Appendix 4: Questions left to answer

...and resources to answer them.