Notes on keys, trusts, certificates and authorities in Java

Russell Bateman
6 July 2022
last update:


Glossary

certificate authority (CA) also, "certification authority," an entity that stores, signs and issues digital certificates.
certificate signing request (CSR) an encoded file providing a way to send your public key as well as information identifying the owner of that key (company name, domain name, etc.)
digital certificate also, "public key certificate," or merely, "certificate." An electronic document, typically a file, used to prove the validity of a public key including, as it does, information about the key, the identity of its owner (the "subject") and the digital signature of an entity that has verified the certificate's contents (called the "issuer").
Hypertext Transfer Protocol Secure (HTTPS) an extension of HTTP used for secure communication over a network.
Java KeyStore (JKS) a repository of security artifacts, either authorization certificates or public key certificates, plus corresponding private keys, used in TLS
Rivest-Shamir-Adleman (RSA) one of the oldest public-key cryptosystems widely used for secure-data transmission.
Transport Layer Security (TLS) a cryptographic protocol designed to provide communications over a network, widely used for e-mail, instant messging, VoIP and for securing HTTPS. Formerly, TLS was called Secure Sockets Layer (SSL).

The Java Development Kit

The JDK maintains a certificate authority (CA) keystore file, cacerts, on the path, jre/lib/security. It provides keytool to manipulate the keystore. See The keytool Command.

keytool is a key and certificate-management utility that permits users to manage their own public/private key pairs and certificates. It also allows users to cache certificates. This tool stores the keys and certificates in what's called a keystore. By default, the keystore is simply a file.

When creating a Java keystore, first is created the .jks file initially containing only the private key. Later, a certificate-signing request (CSR) is generated and a certificate generated from that. Then, that certificate is imported into the keystore including any root certificates.

keytool

Commands for creating or adding data to the keystore
-gencert
-genkeypair
-genseckey
-importcert
-importpass

Command for importing contents from another keystore
-importkeystore

Command for generating a certificate request
-certreq

Command for exporting data
-exportcert

Commands for displaying data
-list
-printcert
-printcertreq
-printcrl

Commands for managing the keystore
-storepasswd
-keypasswd
-delete
-changealias

Commands for displaying security-related information
-showinfo

Manual

russ@tirion ~/dev/ps-notes $ keytool --help
Key and Certificate Management Tool

Commands:

 -certreq        Generates a certificate request
 -changealias    Changes an entry's alias
 -delete         Deletes an entry
 -exportcert     Exports certificate
 -genkeypair     Generates a key pair
 -genseckey      Generates a secret key
 -gencert        Generates certificate from a certificate request
 -importcert     Imports a certificate or a certificate chain
 -importpass     Imports a password
 -importkeystore Imports one or all entries from another keystore
 -keypasswd      Changes the key password of an entry
 -list           Lists entries in a keystore
 -printcert      Prints the content of a certificate
 -printcertreq   Prints the content of a certificate request
 -printcrl       Prints the content of a CRL file
 -storepasswd    Changes the store password of a keystore
 

Examples

See The Most Common Java Keytool Keystore Commands.

# generate a Java keystore and key pair
keytool -genkey -alias mydomain -keyalg RSA -keystore keystore.jks -keysize 2048

# Generate a certificate signing request (CSR) for an existing Java keystore
keytool -certreq -alias mydomain -keystore keystore.jks -file mydomain.csr

# Import a root or intermediate CA certificate to an existing Java keystore
keytool -import -trustcacerts -alias root -file Thawte.crt -keystore keystore.jks

# Import a signed primary certificate to an existing Java keystore
keytool -import -trustcacerts -alias mydomain -file mydomain.crt -keystore keystore.jks

# Generate a keystore and self-signed certificate
keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048

# Check a stand-alone certificate
keytool -printcert -v -file mydomain.crt

# Check which certificates are in a Java keystore
keytool -list -v -keystore keystore.jks

# Check a particular keystore entry using an alias
keytool -list -v -keystore keystore.jks -alias mydomain

# Delete a certificate from a Java Keytool keystore
keytool -delete -alias mydomain -keystore keystore.jks

# Change a Java keystore password
keytool -storepasswd -new new_storepass -keystore keystore.jks

# Export a certificate from a keystore
keytool -export -alias mydomain -file mydomain.crt -keystore keystore.jks

# List trusted CA certs
keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacerts

# Import New CA into trusted certs
keytool -import -trustcacerts -file /path/to/ca/ca.pem -alias CA_ALIAS -keystore $JAVA_HOME/jre/lib/security/cacerts

Certificates

Types of certificates include:

  1. TLS/SSL server certificate
  2. TLS/SSL client certificate
  3. E-mail certificate
  4. Self-signed and root certificates
  5. Other...

Certificate authority

A certificate authority (CA) is responsible for signing certificates. Certificates act as an introduction between two parties—as a trusted third party. A CA processes requests from people or organizations requesting certificates, verifies the information and signs an end-entity certificate based on that information.

Mutual SSL authentication

Note: Image probably copyright © by Code Project.

Appendix: more notes...

Here we are securing AppController servlet access by supplying matching URL of <security-constraint> which means that the requester must provide a valid username and password to access the resource. This security only applies to the GET method using BASIC authentication as specified in <login-config>, ending up being the browser-specific standard log-in dialog.

Steps

  1. Prepare project:
    1. Create web application using <maven-archetype-webapp>.
    2. In pom.xml, add javax.servlet-api:3.0.1 as dependency.
    3. In pom.xml, add tomcat9-maven-plugin to run it as an embedded server. We must provide modified tomcat-users.xml.
    4. No need for index.jsp.
  2. Create servlet class, AppController.java, annotated with @WebServlet and @ServletSecurity.
  3. Run web application:
    $ mvn clean tomcat9:run-war
    
  4. Launch browser to http://localhost:8080/servlet-security-example/.

Jersey JAX-RS annotations—this is more like it!

https://www.ibm.com/docs/en/was/9.0.5?topic=applications-securing-jax-rs-resources-using-annotations

<web-app id="WebApp_someID">
  <servlet>
    <servlet-name>AddressBookAppSample</servlet-name>
    <servlet-class>
      org.apache.wink.server.internal.servlet.RestServlet
    </servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>jaxrs.sample.AddressBookApplication
      </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>AddressBookApp</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <security-constraint id="SecurityConstraint_1">
    <web-resource-collection id="WebResourceCollection_1">
      <web-resource-name>AddressBookAppSample</web-resource-name>
      <description>Protection area for Rest Servlet</description>
      <url-pattern>/*</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
      <http-method>PUT</http-method>
    </web-resource-collection>
    <auth-constraint id="AuthConstraint_1">
      <description>Role1 for this rest servlet</description>
      <role-name>Role</role-name>
    </auth-constraint>
    <user-data-constraint id="UserDataConstraint_1">
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
  </security-constraint>

  <security-role id="SecurityRole_1">
    <description>This Role is used to drive authentication </description>
    <role-name>Role1</role-name>
  </security-role>

  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>test realm</realm-name>
  </login-config>
</web-app>

Java servlet code.

@Path( value="/addresses" )
@PermitAll
public class AppController
{
  @GET
  @Produces( value="text/plain" )
  public String getList() { }

  @RolesAllowed( "Administrator" )
  @PUT
  public void updateList( String books ) { }
}

This might be more what we want...

...because what's just above, though JAX-RS, is more complicated: we don't need roles because (my) microservices tend to be just one thing.

https://www.ibm.com/docs/en/was/9.0.5?topic=applications-securing-jax-rs-clients-by-using-ssl

...or, even better, no more than this:

https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html

To install and configure TLS/SSL support on Tomcat 9, follow these steps:

  1. Create a keystore file to store the server's private key and self-signed certificate—specifying a password value of changeit:
    $ keytool -genkey -alias tomcat -keyalg RSA
    
  2. In server.xml, uncomment the entry...
    SSL HTTP/1.1 Connector
    
  3. Modify according to Configuration.

Appendix 2: Links