Wednesday, 3 March 2010

SSL, tomcat and self signed certificates

I have been through the process of getting an application to work via https before but I have always muddled through and never documented exactly what I have done.

I must also admit that I never quite understood exactly what I had done and why.

One problem is that I can not find one place that covers everything you need in one place.

Now I think I am pretty well there.

This post describes what I have done to get a simple client application working using HTTPS posting to tomcat server and using a self signed certificate with the help of several refereneces in particular:

The last reference has a chapter which is pretty well SSL for dummies and explains things very nicely.

The steps that need to be done are:
  1. Create a self signed certificate authority (CA)
  2. Sign a test key via the CA
  3. Add both these keys to a keystore
  4. Setup the application (client) and tomcat (the server) to use this keystore.

1) Create a self signed certificate authority (CA) and keystore

This is described in How to create a self signed certificate, but I will show the steps here

What is happening here:
you will create a CA that later will be added to your keystore file. By adding this CA to your keystore you are saying it is trusted like verisign and any certificates signed by it are then also trusted.


1.1) make a directory to hold the certs and keystore. This might be something like:
C:\ssl
1.2) generate a private key for the server
openssl genrsa -des3 -out server.key 1024
1.3) generate a CSR (Certificate Signing Request)
openssl req -new -key server.key -out server.csr
1.4) Remove the passphrasse from the key
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key

1.5) Generate the self signed certificate
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

2) Create a certificate for tomcat and add both to the keystore

2.1) cd to where the keystore is held. This might be something like:
C:\ssl

2.2) Create a keypair for 'tomcat'
keytool -genkey -alias tomcat  -keyalg RSA -keystore tomcat.ks

2.3) Generate a CSR (Certificate Signing Request) for tomcat
keytool -keystore tomcat.ks -alias tomcat -certreq -file tomcat.csr

2.4) create unique serial number
echo 02 > serial.txt

2.5) Sign the tomcat CSR
openssl x509 -CA server.crt -CAkey server.key -CAserial serial.txt -req -in tomcat.csr -out tomcat.cer -days 365

2.6) Import the server CA certificate into the keystore
keytool -import -alias serverCA -file server.crt -keystore tomcat.ks

2.7) add the tomcat certificate to the keystore
keytool -import -alias tomcat -file tomcat.cer -keystore tomcat.ks

3) Tomcat configuration
3.1) Tomcat needs to be configured to use SSL
This is described in more detail at Tomcat SSL Configuration How-To
However all that is needed here is to edit the server.xml to enable SSL
This section is already in the server.xml but commented out.
NB that the location of the keystore has been added.

<!-- 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 port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="C:\ssl\tomcat.ks"
keystorePass="changeit"
clientAuth="false" sslProtocol="TLS" />

3.2) test tomcat
start tomcat and go to https://localhost:8443/

your browser will return an error such as "sites certificate is not trusted"

3.3) import the CA certificate server.crt into your browser's tructed root certificates

3.4) test again at https://localhost:8443/

this time you should see the tomcat home page

4) Test your application

4.1) I have a unit test run from eclipse that I have been using to post off to my test server. This produces the error;
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:289)

4.2) The reason for this is that eclipse is not referring to the keystore that we have created. At the time of writing I have not sussed out how to make eclipse use this - Do you know ?
So instead I have added the same two certs to javas keystore

4.3) cd to the directory where java's keystore is held. This might be something like:
C:\java\jdk1.6.0_18\jre\lib\security

4.4) the keystore is a file called cacerts

4.5) copy the files c:\ssl\server.crt and c:\ssl\tomcat.cer to this directory

4.6) import the server CA into the java keystore
keytool -import -alias serverCA -file server.crt -keystore cacerts
4.7 import tomcats cert into the java keystore
keytool -import -alias tomcat -file tomcat.cer -keystore cacerts

5) Test your app again.
Hopefully all will be hunkdory. Enjoy.

6) Caveats:

6.1) the passwords for all keystores and certs are 'changeit'. this is the default keystore password
and I suggest you change this for a production system

6.2) Using a self signed cert is great for a test environment of for a private system but not for a commercial released application. For this you will need to get & pay for a signed certificate from an approved authority such as Verisign.

23 comments:

Bill Comer said...

Note to self:
I use cygwin as a cmd shell and 'openssl' is installed as part of that, but not by default.
'keytool' can be found in your JDK bin directory

Theja said...

Hi Bill,

Thanks for the post, it was of greate help. Whenver i needed to test https connection, I had always had to go through many websites to collect information. This single article has covered all steps needed to create and use selfsigned certificate with tomcat. Keep up good work.

Theja said...

Hi Bill,

Good article, it saved lot of my time in getting my tomcat enabled https enabled. Keep up good work.

Subbu said...

Thanks Bill!...your post saved my day.

Anonymous said...

That worked for me...Thanks a lot...

simon said...

Thanks Bill...
it's a great, concise guide..

only extra step i had to do was change the protocol to "org.apache.coyote.http11.Http11NioProtocol" to solve the "did not find a matching property" errors

Hua said...

Bill,

Wonderful post. I followed the instructions in your post, but still could not display a "Hello World" page using https. No errors - just sits there with no response. Http worked fine.

Any suggestions on how I can go about troubleshooting the problem? I like to use this as a learning experience. Thanks again!

Bill Comer said...

Hua,
Without more info, no. Check through all the steps again. Does 3.4 work ? Check the keystore files with the cmd 'keytool -list'.

Hua said...

Bill,

Following your suggestions, I did some more testing:
1. Checked for typos and re-did the keystore & certificates.
2. https://myServer:8443/ did not return any errors. Just sits there.
3. Verified server islistening on port 8443 (using both netstat -a and telnet myServer 8443)
4. keytool -list returned to entries: serverca and tomcat
5. Verified http://myServer:8080/ returned Tomcat page.

How do I go about to trouble shoot this? Thanks.

Bill Comer said...

So by 'Just sits there' I take it step 3.4 does not show the tomcat home page. Therefore the problem is before there. Check 3.1, check your browsers trusted certs, check ...

Anonymous said...

I followed all commands with success, but when I go into my site, I am still getting the "Certificate Error" page.

Can you help me with this?

Bill Comer said...

Yep, check again at every step. To be honest it is very difficult to help remotely. Double check. Does 3.2 pass. Check the certificate is in the browser by going to Options/Content/certificates (for IE atleast).

DJ Sonitus said...

thank you very much Bill!!! I had to do something very similar to this today. I got two instances to talk to each other using https to pass messages around. It works great! I've been digging around, but this post was THE MOST HELPFUL blog I ran into.

Anonymous said...

very helpful!!!!

Anonymous said...

what file i will send to client
for the java program trust my website

Bill Comer said...

I think it is tomcat.cer from step 2.6 but please bear in mind this is just for Self Signed certs and MUST not be used for production systems

f8w said...

very useful. I couldn’t have done it without you”

f8w said...

very useful. I could no’t have done it without you”

Anonymous said...

very useful, thank you

Ram said...

Hi Bill, This post is great. I want the unit testing code of your eclipse. Can you give atleast the algorithm of how to connect to ssl configured tomcat server using a java client?

Bill Comer said...

Ram,
see http://billcomer.blogspot.co.uk/2010/07/getting-eclipse-to-connect-to-running.html

Tom said...

Just wanted to say thanks for this. Been struggling all day trying to get this figured out. Your steps worked perfectly.

Anonymous said...

very helpful. Excellent article.