AWG Blogs

Saturday, March 5, 2016

Two-way authentication with Tomcat

Start by creating a private key, cert, and keystore using openssl then convert to jks using Java's keytool so it can be used in Tomcat:
MyOwnPC+Joe@MyOwnPC ~/temp
$ openssl req -new -x509 -key serverprivatekey.pem -out servercert.pem -days 1095
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:.
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:myownpc
Email Address []:.

MyOwnPC+Joe@MyOwnPC ~/temp
$ ls
servercert.pem  serverprivatekey.pem

MyOwnPC+Joe@MyOwnPC ~/temp
$ openssl pkcs12 -export -out serverkeystore.pkcs12 -in servercert.pem -inkey serverprivatekey.pem -name myownpc -passout pass:changeit

MyOwnPC+Joe@MyOwnPC ~/temp
$ ls
servercert.pem  serverkeystore.pkcs12  serverprivatekey.pem

MyOwnPC+Joe@MyOwnPC ~/temp
$ keytool -importkeystore -alias myownpc -srckeystore serverkeystore.pkcs12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS
Enter destination keystore password:  changeit
Re-enter new password: changeit
Enter source keystore password:  changeit

MyOwnPC+Joe@MyOwnPC ~/temp
$ ls
keystore.jks  servercert.pem  serverkeystore.pkcs12  serverprivatekey.pem

MyOwnPC+Joe@MyOwnPC ~/temp
$ cp keystore.jks ../certs
Add (or modify) so that Tomcat's conf/server.xml contains reference to the new keystore:
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
        keystoreFile="C:/cygwin64/home/Joe/certs/keystore.jks" keystorePass="changeit"
               clientAuth="false" sslProtocol="TLS" />
Restart Tomcat. Then browse to https://myownpc:8443/someapp. Accept the certificate browser warnings and verify that the presented certificate's details contains 'myownpc' as the 'issued for'. Also you can check using the following keytool command to ensure 'myownpc' is an alias for the imported cert: keytool -list -v -keystore keystore.jks Now create a client certificate and add it to the keystore used by tomcat:

MyOwnPC+Joe@MyOwnPC ~/temp
$ openssl genrsa -out clientprivatekey.pem 2048                                 Generating RSA private key, 2048 bit long modulus
.......................+++
.............+++
e is 65537 (0x10001)

MyOwnPC+Joe@MyOwnPC ~/temp
$ openssl req -new -x509 -key clientprivatekey.pem -out clientcert.pem -days 365
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:.
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:joe
Email Address []:.

MyOwnPC+Joe@MyOwnPC ~/temp
$ ls
clientcert.pem        keystore.jks    serverkeystore.pkcs12
clientprivatekey.pem  servercert.pem  serverprivatekey.pem

MyOwnPC+Joe@MyOwnPC ~/temp
$ openssl pkcs12 -export -out clientkeystore.pkcs12 -in clientcert.pem -inkey clientprivatekey.pem -name joe -passout pass:changeit

MyOwnPC+Joe@MyOwnPC ~/temp
$ keytool -importkeystore -alias joe -srckeystore clientkeystore.pkcs12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS
Enter destination keystore password:  changeit
Enter source keystore password:  changeit

MyOwnPC+Joe@MyOwnPC ~/temp
$ ls
clientcert.pem         keystore.jks           serverprivatekey.pem
clientkeystore.pkcs12  servercert.pem
clientprivatekey.pem   serverkeystore.pkcs12

MyOwnPC+Joe@MyOwnPC ~/temp
$ cp keystore.jks ../certs
Now modify the server.xml SSL connector, adding keyAlias, truststoreFile, and truststorePass attributes and set clientAuth to true:
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
        keystoreFile="C:/cygwin64/home/Joe/certs/keystore.jks" keystorePass="changeit"
               clientAuth="true" sslProtocol="TLS"
  keyAlias="myownpc" truststoreFile="C:/cygwin64/home/Joe/certs/keystore.jks"
  truststorePass="changeit"
 />
Restart Tomcat. Now loading the https page will give an error like
An error occurred during a connection to myownpc:8443. SSL peer cannot verify your certificate. (Error code: ssl_error_bad_cert_alert) 
So in Firefox, do Options, Advanced, View Certificates, Import and import the file clientkeystore.pkcs12 and enter the password when prompted. Try loading the page again and Firefox should present you with the option to use the certificate you imported; accept and load the page.

Refs: http://venkateshragi.blogspot.com/2013/04/two-way-ssl-authentication-on-tomcat.html main flow here. Correction, the truststoreFile was actually required for me.
http://www.cloudera.com/documentation/enterprise/5-3-x/topics/cm_sg_openssl_jks.html found correction to above blog, adding -name option to openssl exports.