Search code examples
tomcatsslssl-certificateself-signedkeytool

Tomcat Server/Client Self-Signed SSL Certificate


I have an Apache Tomcat 6.x server running with a self-signed SSL certificate. I want the client to present their own certificate to the server so I can authenticate them based on a database of users. I have it all working based on an example I found online, but the example came with canned certificates and a pre-build JKS datastore. I want to create my own datastore with my own certs but am having no luck.

How do I create a datastore for Tomcat?
How do I create a self-signed certificate for Tomcat?

How do I create a self-signed certificate for the client?
How do I force Tomcat to trust the signature of the client?

I've been playing with java keytool for many hours now.


Solution

  • Finally got the solution to my problem, so I'll post the results here if anyone else gets stuck.

    Thanks to Michael Martin of Michael's Software Thoughts & Ramblings I discovered that:

    keytool by default uses the DSA algorithm when generating the self-signed cert. Earlier versions of Firefox accepted these keys without problem. With Firefox 3 beta 5, using DSA doesn't work, but using RSA does. Passing "-keyalg RSA" when generating the self-signed certificate creates a cert the Firefox 3 beta 5 fully accepts.

    I simply set that flag, cleared all caches in FireFox and it worked like a charm! I am using this as a test-setup for my project and I need to share this with other people, so I wrote a little batch script that creates two SSL certificates. One can be dropped into the Tomcat setup and the other is a .p12 file that can be imported into FireFox/IE. Thanks!

    Usage: first command-line argument is the username of the client. All passwords are "password" (with no quotations). Change any of the hard-coded bits to meet your needs.

    @echo off
    if "%1" == "" goto usage
    
    keytool -genkeypair -alias servercert -keyalg RSA -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" -keypass password -keystore server.jks -storepass password
    keytool -genkeypair -alias %1 -keystore %1.p12 -storetype pkcs12 -keyalg RSA -dname "CN=%1,OU=Unit,O=Organization,L=City,S=State,C=US" -keypass password -storepass password
    keytool -exportcert -alias %1 -file %1.cer -keystore %1.p12 -storetype pkcs12 -storepass password
    keytool -importcert -keystore server.jks -alias %1 -file %1.cer -v -trustcacerts -noprompt -storepass password
    keytool -list -v -keystore server.jks -storepass password
    del %1.cer
    goto end
    
    :usage
    echo Need user id as first argument: generate_keystore [username]
    goto end
    
    :end
    pause
    

    The results are two files. One called server.jks that you drop into Tomcat and another file called {username}.p12 that you import into your browser. The server.jks file has the client certificate added as a trusted cert.

    I hope someone else finds this useful.

    And here is the the XML that needs to be added to your Tomcat conf/sever.xml file (only tested on on Tomcat 6.x)

    <Connector
       clientAuth="true" port="8443" minSpareThreads="5" maxSpareThreads="75"
       enableLookups="true" disableUploadTimeout="true"
       acceptCount="100" maxThreads="200"
       scheme="https" secure="true" SSLEnabled="true"
       keystoreFile="${catalina.home}/conf/server.jks"
       keystoreType="JKS" keystorePass="password"
       truststoreFile="${catalina.home}/conf/server.jks"
       truststoreType="JKS" truststorePass="password"
       SSLVerifyClient="require" SSLEngine="on" SSLVerifyDepth="2" sslProtocol="TLS"
    />
    

    For Tomcat 7:

    <Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
               port="8443" SSLEnabled="true"
               maxThreads="200" scheme="https" secure="true"
               keystoreFile="${catalina.base}/conf/server.jks" keystorePass="password"
               clientAuth="false" sslProtocol="TLS" />