Google
 
 
Home

Main Menu
 Home
 Linux Articles
 FreeBSD Articles
 Apache Articles
 Perl Articles
 Other Articles
 Program Downloads
 Free Books
 News
 The Web Links
 Contact Us

Most Read
Automating SFTP using expect
FreeBSD PPTP VPN
Shorewall Router on Linux
SnortShorwall - Using Snort And Shorewall Together
Shorewall Stand Alone Firewall

Polls
Favorite Linux/BSD
Fedora
Mandrake
Debian
Slackware
Gentoo
Suse
FreeBSD
Other
  

Syndicate
Latest news direct to your desktop
RSS

Login Form
Username

Password

Remember me
Forgotten your password?
No account yet? Create one

Members Online
 Linux-BSD-Central Has a Total of 701 Members   Members (701) # Online
 We have 5 Guests Online. Guests 5
 We have 0 Users Online. Users 0

Online Users
No Users Online

Statistics
OS: Linux w
PHP: 5.2.9
MySQL: 5.0.91-community
Time: 14:44
Members: 701
Hits: 1324415
News: 277
WebLinks: 15



-->

Tomcat X509 Certificate Authentication   PDF  Print  E-mail 
Contributed by Chad Brandt  
Saturday, 14 February 2009

There are times when you need to secure access to a web application or service and you would like to use client certificates for authentication. This is a common way to secure web service calls and safely authenticate the client. This is not really difficult to do, but there is a lot of steps involved

I recently did this for a project and I was amazed at how confusing it was and the fact there was no website that went thru all the steps. I would find a little documentation here and there from a lot of different websites. I am putting the full instructions here for other as well as myself in the event I have to do this again. This example uses openssl, keytool, and jetty.jar

At a high level we are going to do the following things

  • Create a Certificate Authority (CA). This is for testing purposes only
  • Create a server certificate signed with the CA and export it in PKCS12 format
  • Create your client certificates signed with the CA and export them in PKCS12 format


1.) Create your working directories and working files
# mkdir demoCA
# mkdir demoCA/private
# mkdir demoCA/newcerts
# touch index.txt
# echo "0001" > serial
# echo "0001" > crlnumber



These steps are to create the CA

2.1.) Generate a key for the CA
# openssl genrsa -des3 -out ./demoCA/private/cakey.pem 2048

2.2.) Convert the key you generated into a self-signed CA certificate
# openssl req -new -x509 -key ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem



Now create the certificate for the server

3.1) Generate a key for the server cert
# openssl genrsa -des3 -out server-key.pem 1024

3.2) Create a signing request. This would be sent to Verisign. When you answer the questions the Common Name has to be the domain name of your website
# openssl req -new -key server-key.pem -out server-req.pem

3.3) Create the certificate signed by the CA
# openssl ca -in server-req.pem -out server.pem -notext

3.4) Export the certificate in pkcs12 format.
# openssl pkcs12 -export -in server.pem -inkey server-key.pem -certfile ./demoCA/cacert.pem -out server.p12 -name "Server p12 Certificate"



Now create the certificate for the client. Repeat this step for each client cert you need just change the name of the keys/certs

4.1) Generate a key for the client certificate
# openssl genrsa -des3 -out xmlclient-key.pem 1024

4.2) Create a signing request for the client cert
# openssl req -new -key xmlclient-key.pem -out xmlclient-req.pem

4.3) Create the certificate using our CA
# openssl ca -in xmlclient-req.pem -out xmlclient.pem -notext

4.4) Export the certificate in pkcs12 format
# openssl pkcs12 -export -in xmlclient.pem -inkey xmlclient-key.pem -certfile ./demoCA/cacert.pem -out xmlclient.p12 -name "WebService Certificate"

Now Import that certificate on the client. If this is going to be used to authenticate firefox you need to import the xmlclient.p12 file in firefox on advanced->encryption->view certificates->Your Certificates->Import. If you are going to be using this in IE or a windows application like C# you need to import the xmlclient.p12 into windows by double clicking on the file

Now we are finished creating our certificates. Now we need to create our truststore and keystore that tomcat will use to authenticate with


Create the truststore tomcat will use

5.) We will use keytool to create a truststore named server.truststore
# keytool -import -v -keystore server.truststore -storepass yourpassword -file ./demoCA/cacert.pem

Copy the server.truststore to a place for tomcat, I usually copy it to $TOMCAT_HOME/conf directory



Create the keystore tomcat will use by importing your server key in pkcs12 format
NOTE: keytool does not allow you to import pkcs12 format keys so we will use a tool from jetty to do this. Download jetty and copy jetty-.jar to your ssl working directory

6.) Execute jetty tool to import key
# java -classpath ./jetty-6.0.2.jar org.mortbay.jetty.security.PKCS12Import server.p12 server.keystore

Copy the server.keystore to a place for tomcat, I usually copy it to $TOMCAT_HOME/conf directory



Configure Tomcat

Uncomment the SSL adaptor configuration in server.xml and change clientAuth="true" and add entries for the keystore and truststore. Your adaptor should look something like this

    <Connector port="8443" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="true" sslProtocol="TLS" 
               keystoreFile="/usr/local/apache-tomcat-5.5.27/conf/server.keystore"
               keystorePass="yourpassword"
               truststoreFile="/usr/local/apache-tomcat-5.5.27/conf/server.truststore"
               truststorePass="yourpassword" />
You have to change clientAuth="true" or the server will not use the client certificate to authenticate



Use the p12 certificate in Java (Using commons http client)


EasySSLProtocolSocketFactory easySSL = new EasySSLProtocolSocketFactory();
KeyMaterial keyMaterial = new KeyMaterial("c:xmlclient.p12", password.toCharArray());
easySSL.setKeyMaterial(keyMaterial);

Protocol easyhttps = new Protocol("https", (ProtocolSocketFactory) easySSL, 443);
Protocol.registerProtocol("https", easyhttps);

MultiThreadedHttpConnectionManager connectionManager = new
MultiThreadedHttpConnectionManager();

connectionManager.getParams().setDefaultMaxConnectionsPerHost(500);
connectionManager.getParams().setMaxTotalConnections(2000);

HttpClient httpClient = new HttpClient(connectionManager);


PostMethod postMethod = new PostMethod();

try {
        postMethod.setURI(new URI("https", null, host, 443, url));
        postMethod.setRequestEntity(new ByteArrayRequestEntity(payload.toString().getBytes()));
        postMethod.setRequestHeader("Content-Type", "text/xml");
        httpClient.executeMethod(new HostConfiguration(), postMethod, new HttpState());

        String responseXml = postMethod.getResponseAsString();
}
finally {
        postMethod.releaseConnection();
}





Use the .p12 file in C#
private string SendXml(string url, string data)
{

            X509Certificate certificate = new X509Certificate2(
                @"c:xmlclient.p12,"password");

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.ClientCertificates.Add(certificate);
            request.KeepAlive = false;
            request.ProtocolVersion = HttpVersion.Version10;
            request.Method = "POST";

            byte[] postBytes = Encoding.ASCII.GetBytes(data);
            request.ContentType = "text/xml";
            request.ContentLength = postBytes.Length;
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(postBytes, 0, postBytes.Length);
            requestStream.Close();

            // Pick up the response:
            string result = null;
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                result = reader.ReadToEnd();
            }
            log.Debug(result);
            return result;

}



How to use a real certificate when you get it

Now what to do when you get the real certificate? You need to create a new keystore and truststore

You would do step 3.1 and 3.2 as usual but step 3.3 would not be necessary because this is the certificate you will get from verisign or where ever you order your SSL cert.

Step 3.4 gets replaced with this:

You need to convert the private key and certificate to DER format first
# openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER
# openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER

Now import the existing private key and certificate DER files into a java keystore. keytool does not support this so you have to use java to do this. This site has good instructions To sum it up you would run the code like this
# java ImportKey key.der cert.der
Using keystore-file : /home/user
/keystore.ImportKey One certificate, no chain.
Key and certificate stored.
Alias:importkey Password:importkey

Downlaod ImportKey.class
Downlaod ImportKey.java

After you have imported the key you need to change the alias to tomcat
# keytool -changealias -alias importkey -destalias tomcat -keystore keystore.ImportKey

Change the keystore password to something you want
# keytool -storepasswd -new -keystore keystore.ImportKey

Now convert the root ca public key into DER format and import into keystore

# openssl x509 -in trustca.pem -inform PEM -outform DER -out trustca.crt
# keytool -import -alias trustca -keystore keystore.ImportKey -file trustca.crt

Now your keystore is set to work with tomcat, rename the keystore to whatever you had before and replace the file you were pointing to in tomcat config.

Create the new truststore by importing the certificate you received and the ca public cert into the truststore
# keytool -import -v -keystore server.truststore -storepass yourpassword -file trustca.pem
# keytool -import -v -keystore server.truststore -storepass yourpassword -file servercert.pem

Now copy your new truststore to the file your tomcat config is pointing to

Now you need to create new client certificates that are signed with the server certificate like this:

Steps 4.1, 4.2, and 4.4 all remain the same. NOTE: in step 4.2 the organization MUST be the server name the server certificate is for eg. yourserver.com. You just need to replace step 4.3 with the following

# openssl ca -verbose -in client-req.pem -out client.pem -notext -keyfile server-key.pem -cert server.pem -config ./openssl.cnf -days 365

Make sure your openssl.conf is pointing to the server cert instead of your demoCA certs

Comments

Write Comment
Name:Guest
Title:
BBCode:Web AddressEmail AddressBold TextItalic TextUnderlined TextQuoteCodeOpen ListList ItemClose List
Comment:



Powered by AkoComment 1.0 beta 2!




 
Google Ads



 

Check out TwistByte - The best mobile apps available For awesome Android and IPhone applications!!