on software development and possibly other things

Setting-up Tomcat SSL with StartSSL Certificates

7 comments
Part of an effort to improve the security of CheckTheCrowd.com is to enable SSL on my web server. Enabling SSL allows it to support HTTPS connections.

The CheckTheCrowd web application is hosted on Apache Tomcat which provides a pretty good, albeit generic documentation on how to achieve this setup.

In summary, enabling SSL on Tomcat requires three things:
  • Creating a Java keystore which contains the private key that Tomcat would use to start SSL handshakes
  • Ensuring that you or your website owns the private key by having it signed by a trusted authority which in turn, issues a digital certificate verifying your ownership of the key
  • Configuring a Tomcat connector to listen on HTTPS from a specified port
Creating a keystore and configuring a Tomcat connector is simple enough. However, acquiring an SSL certificate from a trusted provider can be expensive.

Thankfully,  I heard about StartSSL which provides free SSL certificates with one year validity (a new one can be generated upon expiry).

Below are the steps I took to set-up Tomcat SSL using StartSSL certificates.

1. Creating the Java Keystore File (.jks)

As per the Tomcat documentation, the first thing I needed to do was to generate a Java keystore which would hold my private key. This was done by using the keytool command that is part of JDK.
keytool -genkey -keysize 2048 -keyalg RSA -sigalg SHA1withRSA \
  -alias [name of server] -keystore [name of keystore].jks \
  -keypass [password] -storepass [password] \
  -dname "CN=[domain name], OU=Unknown, O=[website], L=[city], ST=[state], C=[country]"
Note that due to a Tomcat limitation, the keypass and storepass must be the same. The dname entry is optional; if not provided, these details will be asked by keytool during the process.

Example:
keytool -genkey -keysize 2048 -keyalg RSA -sigalg SHA1withRSA \
  -alias webserver -keystore checkthecrowd.jks \
  -keypass ****** -storepass ****** \
  -dname "CN=checkthecrowd.com, OU=Unknown, O=CheckTheCrowd, L=Singapore, ST=Unknown, C=SG"
At this point, my keystore already contains the private key required by Tomcat to start an SSL connection.

I can already start using this keystore to enable SSL in Tomcat, but a rogue entity can hijack the connection and pretend that his private key was issued by CheckTheCrowd. This rogue entity can then trick my users that they are securely connected to CheckTheCrowd when in fact they are connected to something else.

To solve this, I need to acquire a signed certificate to prove that my private key is associated to my domain (checkthecrowd.com).

2. Creating a Certificate Request File (.csr)

A certificate request is submitted to a certificate provider and an SSL certificate is generated based on this file.
keytool -certreq -alias [name of server] -file [name of request].csr \
  -keystore [name of keystore].jks
Note that this command would ask for the password previously set for the keystore.

Example:
keytool -certreq -alias webserver -file checkthecrowd.csr \
  -keystore checkthecrowd.jks

3. Submitting the Certificate Request to StartSSL

I needed to signup for an account in order to use StartSSL. Signing-up involves generating a signed private key which proves my identity. Here onwards, the key is used by StartSSL to authenticate my access to their website.

Note that it is important to keep a back-up copy of this private key for future use. This file needs to be imported on all computers used to access StartSSL.
Figure 1: StartSSL
Once I have an account, I can use the Control Panel to generate my certificate. The first step is to validate that I own the domain checkthecrowd.com. The aptly named Validation Wizard takes care of this.

Once my domain is validated, I used the Certificates Wizard to submit my certificate request (.csr file):
  • Select Web Server SSL/TLS Certificate.
  • Because I already have a private key and a certificate request, I skip the next screen
  • I pasted the contents of my certificate request (.csr file) to the text area provided
  • When finished, the generated certificate is displayed on another text area -- I copied this and saved to a file called ssl.crt.
4. Import the Generated Certificate and StartSSL Certificate Chains

The next step is import the generated certificate to my keystore. The StartSSL certificate chain is also required to be imported.

The StartSSL certificate chain can be downloaded from:
The free SSL certificate from StartSSL is only a Class 1 level certificate. If using an upgraded package, all applicable class certificates should be used. Other formats like .pem or .cer can also be used, see http://www.startssl.com/certs/.

I again used keytool to import these certificates:
keytool -import -alias [ca alias] -file [ca file].crt \
  -keystore [keystore name].jks -trustcacerts
keytool -import -alias [class1 alias] -file [class1 file].crt \
  -keystore [keystore name].jks -trustcacerts
keytool -import -alias [name of server] -file ssl.crt \
  -keystore [keystore name].jks
The first two commands imported the certificate chain as trusted certificates, the last command imported the signed certificate.

Example:
keytool -import -alias startsslca -file ca.crt \
  -keystore checkthecrowd.jks -trustcacerts
keytool -import -alias startsslca1 -file sub.class1.server.ca.crt \
  -keystore checkthecrowd.jks -trustcacerts
keytool -import -alias webserver -file ssl.crt \
  -keystore checkthecrowd.jks
Listing the contents of my keystore verified that I have 3 certificates:
$ keytool -list -keystore checkthecrowd.jks
webserver, Aug 5, 2013, PrivateKeyEntry,
Certificate fingerprint (SHA1): [...]
startsslca, Aug 5, 2013, trustedCertEntry,
Certificate fingerprint (SHA1): [...]
startsslca1, Aug 5, 2013, trustedCertEntry,
Certificate fingerprint (SHA1): [...]

5. Configure Tomcat with SSL

Enabling SSL with Tomcat involves creating a new connector which listens to HTTPS connections. This connector needs to know the location of the keystore file as well as the password to access the keystore.

For convenience, I placed my keystore under $TOMCAT_HOME.
<!-- 
Define a SSL HTTP/1.1 Connector on port 8443
This connector uses the JSSE configuration, when using APR, the
connector should be using the OpenSSL style configuration
described in the APR documentation 
-->
<Connector
  protocol="HTTP/1.1"
  port="8443" maxThreads="200"
  scheme="https" secure="true" SSLEnabled="true"
  keystoreFile="checkthecrowd.jks" keystorePass="******"
  clientAuth="false" sslProtocol="TLS"/>
Note that by default, the Tomcat HTTPS port is 8443.

That's all there is to it! After bouncing Tomcat, I am now able to access CheckTheCrowd via HTTPS from port 8443: https://checkthecrowd.com:8443/.

The next step is to configure Apache httpd to forward HTTPS requests to port 8443. I still haven't figured out how to do this yet, so if you have an idea, let me know!

7 comments :

  1. You can use mod_proxy, or mod_jk.

    ReplyDelete
  2. Great instructions, helped a lot! Thank you!

    ReplyDelete
  3. Hello! I can Apache Tomcat and StartSSL Certificate. Maybe create alias Auth Cetrifcate p12?

    ReplyDelete
  4. Hi, that indeed looks like a step I have missed. You need to convert the crt files into pem format.

    You can do this via openssl. Take a look at this SO answer for an example:
    http://stackoverflow.com/a/4691749/1719065


    Let me know if this works and I'll update the post to include this step.


    Cheers!

    ReplyDelete
  5. I think that it is better to download http://www.startssl.com/certs/ ready certificates. Because OpenSSL does not work, or am I doing something wrong. :(

    root@linux:/# openssl x509 -in ca.crt -out ca.pem -outform PEM
    unable to load certificate
    140326105921184:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: TRUSTED CERTIFICATE

    ReplyDelete
  6. Cheers! I will update links with your suggestion.

    ReplyDelete