Archive for December, 2005

12.18.05

Sign of the times …

Posted in SOA at 10:47 pm by kkj

How do you provide a security infrastructure, which leverages digital certificates installed at disparate locations to provide single-signon to a federation of services over a virtual private network? This is one of the questions we’re currently tackling in a governmental project coined SOSI for Service Oriented System Integration.

The project builds on a suite of technologies to enable service providers within the Danish Healthcare Domain to collaborate without compromising patient rights and security constraints. A cornerstone in the currently envisioned architecture, SAML 2.0 provides the enabling technology, which allows the participants to exchange messages in a secure manner.

The SAML profiles for Web SSO and Web Services rely heavily on PKI to provide digital signatures of content and assertions, hence allowing a receiver to verify the integrity of messages. In its strategy for The Danish Healthcare Sector, The Danish National Board of Health has decided to follow recommendations from The Ministry of Science, Technology, and Innovation and employ the socalled OCES certificates for PKI. These are X.509 certificates with 1024 bit RSA keys, using SHA1 with RSA as the signature algorithm.

While we’ll probably be using some product that implements SAML 2.0, OSS or commercial, I decided to find out how much work is actually involved in writing a piece of Java code for signing data and verifying signatures under standard JCE.

And now we’ve reached the actual topic of this post :-).

So without further ado, here is the Java way to create a digital signature of some piece of data and verify it again using your OCES digital certificate:

Export the OCES certificate:
If you’re an IE user, go to tools -> internet options -> content -> certificates. Select the OCES certificate, and choose export. Don’t forget to export the private key as well. If the private key is not enabled for export, you can use the export tool from TDC to get it out. Assuming you succeed and have stored the certificate with its private key in PKCS12 (PFX) format under “keystore.pfx”, you can move onto the next step.

Create the Java Keystore:
Java uses its own format for storing cryptographic keys called JKS for Java KeyStore. The JDK ships with “keytool”, which among other things can create a fresh keystore. There is no command to create an empty one, but you can use the -genkey command to generate a dummy key, which can then be deleted:

keytool -genkey -keystore keystore.jks -storepass ... -alias mykey
keytool -delete -keystore keystore.jks -storepass ... -alias mykey

Genkey prompts you for personal information to store with the certificate. Just supply dummy values.

Import the PCKS12 file:
The friendly people at Sun have made a tool for keystore management, called “keytool”, which ships with the JDK. Unfortunately this tool does not know how to import the contents of a PKCS12 file into a JKS keystore. No need to panic, though, because the same people or their friendly colleagues have made another tool, “pkcs12import.bat”, which does the trick. To get it, you will need to download the Sun Java Web Services Pack which is around 70 MB (see references).

  pkcs12import.bat -file keystore.pfx -alias mycert -keystore keystore.jks

Create the signature
Once the keystore is ready, you can sign a piece of data with its key. The code snippet below shows how this is done with constants expanded, and exception handling and functional decompositions ommitted for clarity:

  // Load the data to sign into memory
  byte[] data = readByteFile(datafile);
  
  // Load the keystore into memory
  keyStore = KeyStore.getInstance(”JKS”);
  keyStore.load(new FileInputStream(file), password.toCharArray());
  
  // Get the private key to sign with
  PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keypass.toCharArray());
  
  // Sign the data
  byte[] result;
  Signature sign = Signature.getInstance(”SHA1withRSA”);
  sign.initSign(privateKey);
  sign.update(data);
  result = sign.sign();

Verify the signature
Assuming the keystore and data files have already been loaded as shown previously, we only need to get the public key and verify the signature:

  // Get the public key for verification
  java.security.cert.Certificate certificate = keyStore.getCertificate(alias);
  PublicKey publicKey = certificate.getPublicKey();
  
  // Verify the signature
  Signature sign = Signature.getInstance("SHA1withRSA");
  sign.initVerify(publicKey);
  sign.update(data);
  result = sign.verify(signature);

The tool
The source supplied with this post comprises a full commandline tool with the following syntax:

Signtool usage

-sign -keystore <keystore> -storepass <storepass> -alias <keyalias> -keypass <keypass> -datafile <data> -sigfile <signaturefile> [-algorithm <algorithm>]
-verify -keystore <keystore> -storepass <storepass> -alias <keyalias> -datafile <data> -sigfile <signaturefile> [-algorithm <algorithm>]

The tools can be invoked via the $src/bin/sign.cmd command.

This is Kåre Kjelstrøm of Vaportrail, signing off :-) Merry Christmas.

References: