Sunday, June 6, 2010

Creating Trust Store and Identity Key Store for 2 Way SSL Connectivity using Java

In my earlier article, I have highlighted how to connect a URL using 2 way SSL connectivity. While connecting to that URL, we have used two certificate key stores; one is trust store and identity key stores.

However, this article will tell you those key stores using open ssl commands and few java codes.

Let me give you the background before going to the step by step process to create the key stores.

There are generally two kinds of certificates: Client Certificate and Server Certificate.
 
Client certificate is usually installed on a client's browser and provides user identity to the server at the other end. The client certificate is also having a public key and a certificate to the server. This public key is used by the server to encrypt any data exchange between these two parties. Server certificate is installed on the server side and provides server identity, certificate, and public key information to clients that try to establish a connection. The certificate and public key are used for handshaking and further data encryption between client and server.
 
The identity key store is containing the identity of the client certificate, intermediate, root certificate and the private key associated with it. The trust store is containing only the root certificate, which is generally common to the server and client certificate.


First let me go through the steps how to export the client certificate onto your local drive.

 




Now, you have the client certificate in pfx format in your local drive.
Step 1: Creating the Identity Key store:
a. Convert the pfx certificate onto the pem format


Using below open ssl command, you need to convert the pfx certificate onto the pem format

openssl pkcs12 -in client.pfx -out client.pem –nodes



b. The resulting file will have all the certificates in the following order:


Private key, Identity certificate, Root certificate, Intermediate certificate

c. From the client.pem file, copy the private key and paste it in different file, say my_key_pk.pem. It is very easy to identify the private key as it is wrapped with in the following two headers:


-----BEGIN RSA PRIVATE KEY-----



-----END RSA PRIVATE KEY-----



d. From the client.pem file, create a new file (my_key_crt.pem) with the certificates reordered The order is important, otherwise the hosting server will not recognize the certificates:




Identity certificate, Intermediate certificate, Root certificate, Private Key



Now the my_key_crt.pem can be directly used by a Java client to invoking web services over SSL.

e. Now you need to create identity key store while importing private key either by the following two way

1. Using Weblogic Utility:




java utils.ImportPrivateKey -keystore my_key_identity.jks -storepass passw0rd -storetype JKS -keypass passw0rd -alias my_key_crt -certfile my_key_crt.pem -keyfile my_key_pk.pem



OR


1. Convert the Convert both, the key and the certificate into DER format using openssl




openssl pkcs8 -topk8 -nocrypt -in my_key_pk.pem -inform PEM -out my_key_pk.der -outform DER



openssl x509 -in my_key_crt.pem -inform PEM -out my_key_crt.der -outform DER


2. Using the following Java code import the private key and the certificate on to the identity keystore.




import java.security.*;

import java.io.IOException;

import java.io.InputStream;

import java.io.FileInputStream;

import java.io.DataInputStream;

import java.io.ByteArrayInputStream;

import java.io.FileOutputStream;

import java.security.spec.*;

import java.security.cert.Certificate;

import java.security.cert.CertificateFactory;

import java.util.Collection;

import java.util.Iterator;





public class ImportKey {



private static InputStream fullStream ( String fname ) throws IOException {

FileInputStream fis = new FileInputStream(fname);

DataInputStream dis = new DataInputStream(fis);

byte[] bytes = new byte[dis.available()];

dis.readFully(bytes);

ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

return bais;

}





public static void main ( String args[]) {





String keypass = "passw0rd";



String defaultalias = "importkey";



String keystorename = "./my_key_identity.jks";

String keyfile = "./my_key_pk.der";

String certfile = "./my_key_crt.der";



try {



KeyStore ks = KeyStore.getInstance("JKS", "SUN");

ks.load( null , keypass.toCharArray());

System.out.println("Using keystore-file : "+keystorename);

ks.store(new FileOutputStream ( keystorename ), keypass.toCharArray());

ks.load(new FileInputStream ( keystorename ), keypass.toCharArray());



InputStream fl = fullStream (keyfile);

byte[] key = new byte[fl.available()];

KeyFactory kf = KeyFactory.getInstance("RSA");

fl.read ( key, 0, fl.available() );

fl.close();

PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );

PrivateKey ff = kf.generatePrivate (keysp);





CertificateFactory cf = CertificateFactory.getInstance("X.509");

InputStream certstream = fullStream (certfile);



Collection c = cf.generateCertificates(certstream) ;

Certificate[] certs = new Certificate[c.toArray().length];



if (c.size() == 1) {

certstream = fullStream (certfile);

System.out.println("One certificate, no chain.");

Certificate cert = cf.generateCertificate(certstream) ;

certs[0] = cert;

} else {

System.out.println("Certificate chain length: "+c.size());

certs = (Certificate[])c.toArray();

}





ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), certs );

System.out.println ("Key and certificate stored.");

System.out.println ("Alias:"+defaultalias+" Password:"+keypass);

ks.store(new FileOutputStream ( keystorename ), keypass.toCharArray());

} catch (Exception ex) {

ex.printStackTrace();

}

}



}


Step 2: Creating the Trust Java Key Store


Open the my_key_crt.pem file in a text editor, copy the root certificate and paste it to a new file, say my_key_root.pem. You can easily find the root certificate since its issuer and subject headers must be same.

Use the Java key tool utility and import the above my_key_root.pem file to a JKS file:

keytool -import -trustcacerts -file my_key_root.pem -alias my_key_root -keystore my_key_trust.jks -storepass passw0rd

 
 
Now, you have trust store [my_key_trust.jks] and identity key store [my_key_identity.jks] which you have use to connect to a 2 way SSL URL.


Hope you all will find it useful.

Total Pageviews