Programming And Stuff, You Know The Thing…

How to feed free Letsencrypt SSL/TLS certificates to your Java keystore/webapp

Posted at — Oct 9, 2017

I’m currently using free SSL/TLS certificates from https://letsencrypt.org/ to secure this website’s traffic (embed://tag/site-software).

The first step is to acquire your certificates. On a Debian system, simply install certbot. I usually use its standalone mode of operation after shutting down the Java web server, to obtain the certificate files and to generate the encryption key.

Having retrieved the certificates, they will be linked into /etc/letsencrypt/live/<domain>. To create the final keystore from those files, I use the following commands from inside that directory (script):


set -Eex
set -o pipefail

export JAVA_HOME=/opt/jdk8
export PATH=$JAVA_HOME/bin:$PATH

rm -f jetty.pkcs12
openssl pkcs12 -inkey privkey.pem -in fullchain.pem -export -out jetty.pkcs12 -passout pass:password
rm -f keystore
keytool -importkeystore -srckeystore jetty.pkcs12 -srcstoretype PKCS12 -destkeystore keystore -deststorepass password -srcstorepass password
mv -f keystore /home/web/.
chown web.web /home/web/keystore
chmod 600 /home/web/keystore

After starting up the web server (after telling it the password of the keystore file, here “password”), one should verify that the SSL certs are actually working (ie. if the certificate chain is correct). That is important because some browsers don’t have a recent list of intermediary CAs and will therefore not be able to show your site if you miss the intermediary CA cert in your keystore. That’s why we are importing fullchain.pem instead of simply cert.pem. One can do this on a Linux box simply by defining and executing the following command followed by the domain name of your server:

_openssl_dump_remote_certs () 
    echo | openssl s_client -showcerts -connect $1:443 | openssl x509 -text -noout

The first few lines of the output should look like:

root@domain ~ $ _openssl_dump_remote_certs my.domain.com
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = my.domain.com
verify return:1
        Version: 3 (0x2)

The verify returns must be 1 up to DONE.

I also use this command to look up the expiry date of the active certificate.

You can also use online services like SSL Checker instead.

Btw: there is that nice authbind linux tool that allows you to run your server as non-root and still use privileged ports below 1024 without firewall tricks or similar nuisances.