Introduction

EMO has the ability to use passwordless login capabilities via certificate authentication using SSL. As many people will bemoan, however, setting up the Public Key Infrastructure (PKI) to provide this capability is actually fairly difficult.

This guide will walk you through the steps of setting up your own PKI as well as how to set up Tomcat to handle Certificate-based authentication.

The Steps

The basic steps for handling the creation of the PKI are:

  1. Create OpenSSL keys and request
  2. Create a server certificate and keystore
  3. Configure the application server
  4. Issue client certificate

Credits

An excellant resource to assisting you in setting up your Tomcat server to handle Certificate-based authentication is detailed in the book Tomcat: The Definitive Guide by Oreilly Press

Create openSSL keys

Obtain Latest OpenSSL

While other SSL-management systems are available, because OpenSSL is cross platform and free, we will be documenting OpenSSL for the handling of our PKI. However, if you wish to use other PKI-enabling programs, the basic steps outlined in this document will still generally apply.

Most linux distributions these days provide OpenSSL as part of their distribution. If you are a windows user you may obtain a precompiled binary installation package from the OpenSSL web site.

NOTE: Please watch for new releases to the OpenSSL packages. Every few months a new version of OpenSSL is released and most releases contain security-related bugfixes.

Generate key

Once you have OpenSSL properly set up and the OpenSSL binary in your path, execute the following commands (unix OS assumed):

  cd .../emo # your directory where emo is hosted, or wherever you would like keystore info to reside
  mkdir keys
  cd keys # we will generate various files into this directory
  # the following will prompt for a few values to put into the certificate request
  openssl req -new -newkey rsa:1024 -nodes -out ca.csr -keyout ca.key -dname "cn=$DOMAINNAME"
  openssl x509 -trustout -signkey ca.key -days 1825 -req -in ca.csr -out ca.pem
				

OpenSSL has several 'subparts' in its command. The portion of the command line that follows the openssl binary is the portion to use. For example, the first part:

 openssl req ...

deals with X.509 Certificate Signing Request (CSR) Management., whereas

 openssl x509 ...

deals with X.509 certificate data management. So the first command created a Certificate request as well as a new private key for the certificate authority, and the second command created a new Certificate Authority Certificate with a 5 year duration.

At this point in time, you have two main artifacts that need to be protected: ca.key, the private key for the certificate authority, and ca.pem the public certificate of the certificate authority. The private key of the certificate authority must be the most guarded portion of your security! Typically, this is given restricted privileges. If someone manages to steal the Certificate Authority private key, they may issue client certificates in your name.

Create the Serial Number File

Each certificate that is signed by the certificate authority will have a serial number assigned to the signed certificate. It helps when tracing when and where certificates were signed. To create the certificate serial number file in shell environments you can issue the command:

 echo "02" > ca.srl

In a Windows environment, you may simply create a new file called ca.srl, open it with NotePad or equivilant text editor, and give the file the contents 02 and save it.

Create a server certificate and keystore

Create your Tomcat Certificate

Each SSL handshake that is mutually authenticated requires two certificates: One for the server, and one for the client. Java also requires a keystore in which to store the certificate that is used by the Tomcat server.

Generate the keystore with the following command:

    EMO_DIR=`pwd`
    PASS=mypassword
    DOMAINNAME=codeguild.net
    keytool -genkey -dname "cn=$DOMAINNAME" -alias emo -keyalg RSA -keystore $EMO_DIR/emokeystore -keypass $PASS -storepass $PASS
                

The important items in the command line are:

  • emokeystore: You can have any number of keystores, and Java comes with one buried in it. Howver, it is easier to manage if you have Tomcat/emo deal with its own keystore file rather than relying on the one sitting somewhere else.
  • dname: the common name (cn) should be the domain of the web server. You can add a comma and an organziation if you like, e.g.: , o="Codeguild,Inc.". If you leave off the -dname argument you will be prompted for various fields in the certificate.
  • keystore: $EMO_DIR should be set to the full path of the 'keys' directory created above.
  • storepass: $PASS is some password you will remember.
  • alias: can be anything; we use 'emo' for convenience.

Next we import the certificate created in OpenSSL:

 keytool -import -keystore $EMO_DIR/emokeystore -file ca.pem -alias selfca

The items in the command line are:

  • The import loads the certificate.
  • $EMO_DIR/emokeystore : Use the same keystore you created.
  • The alias argument should use the same alias that you used for generating the CSR.

At this point, the keystore should be ready to go for tomcat.

Configure Tomcat For SSL

Open Tomcat's server.xml in the TOMCAT_HOME/conf directory.

Locate the lines:

 <Connector port="8443" maxHttpHeaderSize="8192"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" disableUploadTimeout="true"
    acceptCount="100" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS"
    keystoreFile="conf/tomcatcerts"
    keystorePass="changeit" keyAlias="tomcat"
 />
				

By default, these lines are commented-out, so you probably need to uncomment them.

Set the attributes for keystore file (for us, same as truststore file), etc., to the values you created, such as:

 <Connector port="8443" maxHttpHeaderSize="8192"
	maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" disableUploadTimeout="true"
    acceptCount="100" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS"

    keystoreFile="$EMO_DIR/emokeystore"
    truststoreFile="$EMO_DIR/emokeystore"
    keystorePass="$PASS"
    truststorePass="$PASS"
    keyAlias="emo"
 />

NOTE: replace $EMO_DIR with absolute path

NOTE: replace $PASS with the password

Leave "clientAuth=false" for now.

Fire up tomcat, and using your browser, attempt to connect to https://localhost:8443/. REMEMBER to use https, not http! If you have properly installed the certificate, your browser should prompt you whether you should really connect to this host because the Certificate Authority is not recognized. If you view the certificate you should see all the information you have input when creating the certificate request (CSR) your own certificate authority (CA).

Set Up Client Authentication

Set up Tomcat to Require Client Authentication

Open the TOMCAT_HOME/conf/server.xml file and scroll down to where you enabled the SSL protocol. Change the client authentication attribute to true (clientAuthentication="true"). (Re)start Tomcat. Now if you attempt to connect to the SSL port (8443 by default). You will get an error message. That's good!

Set up Browser-Based Passwordless Logins

The procedure for the browser setup is nearly the same as for the server: first generate a CSR, then have the CA create a certificate.

 openssl req -new -newkey rsa:1024 -nodes -out client1.req -keyout client1.key -subj '/C=US/ST=California/CN=emoclient/EMAILADDRESS=myexpressoemail@mymailhost.com'

The biggest difference here is that the email address on the certificate should be the email address on file (in Emo) of the login that should be used.

Note:For the email address (EMAILADDRESS), use the email address registered in Emo for the desired login.

This generates two artifacts: client1.req, and client1.key.

Now use the CA keys to sign the client:

 openssl x509 -CA ca.pem -CAkey ca.key -CAserial ca.srl -req -in client1.req -out client1.pem

Now client1.pem will be a PEM encoded public key.

Now for the tricky part. Browsers like PKCS#12 certificates WITH a private key included, we have a PEM encoded public key only. So we use OpenSSL along with the client's private key to generate a PKCS#12 encoded certificate that the browser can use:

 openssl pkcs12 -export -in client1.pem -inkey client1.key -out client1.p12 -name "Sample Client Cert"

The components of this command is:

  • client1.pem: The public key signed by the certificate authority.
  • client1.key: The private key that was generated when the CSR was originally generated.

Now copy this file client1.p12 and import it into your browser:

    mkdir clientkey
    cd clientkey
    scp myuser@myserver:/path/to/emo/openkey/client1.p12  .
                

If you are using the Firefox browser, you can reach this via Tools -> Options. Click on the Advanced tab, and click on the "View Certificates" button. The screen displayed will have the option to import a new certificate.

Once you have imported the certificate into your browser, attempt to connect to the SSL port with Tomcat running. If you have more than one client certificate installed in the browser, the browser will ask you which certificate to present. Otherwise, it will attempt to send the only certificate you have available. If things have proceeded correctly, you should now see the Tomcat start page in SSL!

Set up Java Code-based Passwordless Logins

The basic concept is the same as browser-based passwordless logins. But the browser has its own 'truststore' of certificate authorities, and a Java application will default to the one embedded in its VM code. But the default truststore in the client will not know about the self-signed certificate on the server (assuming they are different computers). The browser, when presented with a server self-signed certificate, puts up a dialog asking whether the user wants to trust the server certificate. But a Java application offers no such luxury, and fails immediately. Further, instead of importing the PKCS#12 certificate into the browser, the application USES IT as a keystore.

You can list the contents of your PKCS#12 certificate in the following way:

 keytool -v -list -keystore client.p12 -storetype pkcs12 

That command line argument has the following components:

  • keystore: You directly consider the PKCS#12 certificate as the keystore.
  • storetype: You must tell JAVA that the store type is pkcs12, otherwise, it will try to parse it as a PKCS#7-type public key (which it isn't).

See the Sun JSSE Guide for more information.

The client certificate is only the first part of the chain. You also need a truststore that validates the client certificate. We take a shortcut here and copy the truststore from the server:

  # assume we are in the clientkey directory
  scp myuser@myserver:/path/to/emo/openkey/emokeystore ./clientkeystore
                

Example Complete Startup Values

Put these values (change as necessary, and omit the "-D" prefix) into a file named 'ant.properties' in order to use the ssl-test target in ant. Or make sure they are in the startup script for any Java application you write.

    -Djavax.net.ssl.keyStoreType=pkcs12
    -Djavax.net.ssl.trustStoreType=jks
    # assume directory 'clientkey' is in the emo directory, adjacent to build.xml
    -Djavax.net.ssl.keyStore=clientkey/clientcert.p12
    -Djavax.net.ssl.trustStore=clientkey/clientkeystore
    -Djavax.net.debug=ssl
    -Djavax.net.ssl.keyStorePassword=$PASS
    -Djavax.net.ssl.trustStorePassword=$PASS
			

Troubleshooting Java Client

General Tips

When creating your SSL client in Java, it is always best to use debug output until you have a successful connection. This can be turned on with the command line argument:

 -Djavax.net.debug=ssl

Error: Keystore is not correct type

You must tell Java to use a pkcs12 keystore. This is set with the javax.net.ssl.trustStoreType=pkcs12 system property.

Conclusion

Setting up a PKI (public key infrastructure) is no easy task, but hopefully this document will point you down the right path. If you need assistance setting up your own PKI, CodeGuild can provide consulting to get you going.

For More Information

The Tomcat docs have some good information on getting SSL set up: http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html

There is a sample security chapter in Tomcat: The Definitive Guide available online at http://www.oreilly.com/catalog/tomcat/ Click on "sample chapter" to view the PDF formatted section of the book.