SSL Certificates in Java: Keystores, Truststores, and keytool

How to configure SSL/TLS in Java applications. Covers keytool, PKCS#12 keystores, truststores, Spring Boot TLS, Tomcat SSL, and common Java SSL errors.


Java's SSL Model

Java has its own certificate management system separate from the operating system. Two key concepts:

  • Keystore -- contains your server's certificate and private key (what you present to clients)
  • Truststore -- contains CA certificates you trust (what you use to verify others)

By default, Java uses $JAVA_HOME/lib/security/cacerts as the truststore (password: changeit). This file contains the same root CAs that browsers trust.

Creating a Keystore with keytool

Import a PKCS#12 file

The easiest path. Generate a certificate at getaCert.com, download the .p12 file, and import it:

keytool -importkeystore \
    -srckeystore server.p12 -srcstoretype PKCS12 \
    -destkeystore keystore.jks -deststoretype JKS \
    -srcstorepass password -deststorepass changeit

Since Java 9, you can use the .p12 file directly as a keystore -- no conversion needed.

Generate a self-signed cert with keytool

keytool -genkeypair -alias server \
    -keyalg RSA -keysize 2048 \
    -validity 365 \
    -keystore keystore.jks \
    -storepass changeit \
    -dname "CN=localhost,O=Dev,C=US"

Import a PEM certificate

Java's keytool can't directly import PEM private keys. Convert to PKCS#12 first:

# Convert PEM cert + key to PKCS#12
openssl pkcs12 -export -out server.p12 \
    -inkey server.key -in server.pem \
    -certfile chain.pem -passout pass:password

# Import PKCS#12 into JKS keystore
keytool -importkeystore \
    -srckeystore server.p12 -srcstoretype PKCS12 \
    -destkeystore keystore.jks -deststoretype JKS

Adding a CA to the Truststore

To trust a self-signed certificate or a private CA (like getaCert.com's CA):

# Import CA certificate into a custom truststore
keytool -importcert -alias getacert-ca \
    -file ca-cert.pem \
    -keystore truststore.jks \
    -storepass changeit -noprompt

# Or add it to Java's default truststore
sudo keytool -importcert -alias getacert-ca \
    -file ca-cert.pem \
    -keystore $JAVA_HOME/lib/security/cacerts \
    -storepass changeit -noprompt

Spring Boot HTTPS

application.properties

server.port=8443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=password
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=server

application.yml

server:
  port: 8443
  ssl:
    key-store: classpath:keystore.p12
    key-store-password: password
    key-store-type: PKCS12
    key-alias: server

Place keystore.p12 in src/main/resources/.

Redirect HTTP to HTTPS

@Configuration
public class HttpsRedirectConfig {
    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(httpConnector());
        return tomcat;
    }

    private Connector httpConnector() {
        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);
        return connector;
    }
}

Tomcat SSL Configuration

In server.xml:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
    <SSLHostConfig>
        <Certificate certificateKeystoreFile="conf/keystore.p12"
                     certificateKeystorePassword="password"
                     certificateKeystoreType="PKCS12" />
    </SSLHostConfig>
</Connector>

Useful keytool Commands

# List keystore contents
keytool -list -keystore keystore.jks -storepass changeit

# Verbose listing (shows cert details)
keytool -list -v -keystore keystore.jks -storepass changeit

# Export a certificate from keystore
keytool -exportcert -alias server -keystore keystore.jks \
    -storepass changeit -file server.cer

# Delete an entry
keytool -delete -alias old-cert -keystore keystore.jks \
    -storepass changeit

# Change keystore password
keytool -storepasswd -keystore keystore.jks

Common Java SSL Errors

PKIX path building failed

sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

The server's certificate isn't trusted. Either: - Add the CA certificate to your truststore - Use -Djavax.net.ssl.trustStore=/path/to/truststore.jks - For development: download our CA certificate and import it

No subject alternative names matching

java.security.cert.CertificateException:
No subject alternative names matching IP address 127.0.0.1 found

The certificate's CN or SAN doesn't match the hostname you're connecting to. Generate a new certificate with the correct domain or IP using our self-signed generator -- it supports SAN entries.

Keystore was tampered with

java.io.IOException: Keystore was tampered with, or password was incorrect

Wrong password. The default Java truststore password is changeit. The default getaCert.com PKCS#12 password is password.

Next Steps


More in Guides