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
- Generate a certificate with PKCS#12 download for Java
- Download our CA root certificate for your truststore
- Learn about certificate formats (PEM, DER, PKCS#12)