Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

Tuesday, April 16, 2013

Strategy Pattern Applied - KeyStoreTemplate

Update: I wrongly attributed the design pattern implementation below to the Template pattern, it's actually the Strategy pattern as pointed out by a user in Reddit. However, the article below is kept in its original form, with just the title changed. Sorry for the confusion :)

The Template design pattern is useful if you have methods that follow a similar pattern but differ only in a few places. Usually, the 'generic' method will call one or several abstract methods, which are then implemented in a concrete class.

The JdbcTemplate of the Spring Framework was (and still is) a life saver. No more unclosed Connection objects that may leak to JDBC connection leaks. No more try/catch blocks that obscure the code logic. Converting the JDBC DAOs of legacy systems to use JdbcTemplate objects provided immediate benefits in terms of simplicity (eliminating copy-and-paste codes) and robust resource management (e.g. closing Connections, ResultSets, Statements).

There are a lot of useful articles detailing what, why and how of this design pattern, so I will not rehash them here. I will just document down how I applied this pattern to solve some age-old problem.

I decided to follow the JdbcTemplate's design style to come up with a KeyStoreTemplate, a class that handles importing or exporting of keys to/from a keystore. To make things simple, this class will only handle 2 things: Importing a key, and exporting a key.

Firstly, the KeyStoreTemplate code (abridged for simplicity):


import org.apache.commons.io.IOUtils;

public class KeyStoreTemplate {

 /**
 * Just enough parameters to open a keystore.
 */
 public KeyStoreTemplate(File keyStoreFile, Provider provider, String keyStoreType, String keyStorePassword) {
  this.keyStoreFile = keyStoreFile;
  this.provider = provider;
  this.keyStoreType = keyStoreType;
  this.keyStorePassword = keyStorePassword;
 }

 /**
 * This is to get/export a key from the keystore.
 */
 public Key getFromKeyStore(KeyStoreExporter exporter) {
  FileInputStream fis = null;
  try {
   KeyStore ks = KeyStore.getInstance(keyStoreType, provider);
         fis = new FileInputStream(keyStoreFile);

         //Keystore file must exists!
         if(keyStoreFile.exists()) {
          ks.load(fis, keyStorePassword.toCharArray());
         } else {
          throw new RuntimeException("Keystore file cannot be located!");
         }
         
         String keyPass = keyStorePassword;

         return exporter.exportKey(ks, keyPass);
         
  } catch (Exception e) {
   throw new RuntimeException("Something went wrong!", e);
  } finally {
   IOUtils.closeQuietly(fis);
  }  
 }

 /**
 * This is to save/import a key to the keystore.
 */
 public void saveToKeyStore(KeyStoreImporter importer) {
  
  FileInputStream fis = null;
  FileOutputStream fos = null;
  try {
   KeyStore ks = KeyStore.getInstance(keyStoreType, provider);
         fis = new FileInputStream(keyStoreFile);

         //Keystore file must exists!
         if(keyStoreFile.exists()) {
          ks.load(fis, keyStorePassword.toCharArray());
         } else {
          throw new BusinessException("Keystore file cannot be located!");
         }
         
         String keyPass = keyStorePassword;

         importer.importPrivateKey(ks, keyPass);
         
         fos = new FileOutputStream(keyStoreFile);
         ks.store(fos, keyStorePassword.toCharArray());
         
  } catch (Exception e) {
   throw new RuntimeException("Something went wrong!", e);
  } finally {
   IOUtils.closeQuietly(fis);
   IOUtils.closeQuietly(fos);
  }
 }
 
}


Notice that there are 2 interfaces: KeyStoreExporter and KeyStoreImporter. These interfaces are implemented by the caller class of KeyStoreTemplate to do the 'effective' stuff, without worrying about the KeyStore details. The KeyStore object is passed in, much like the ResultSet object is passed in when using JdbcTemplate.


import java.security.GeneralSecurityException;
import java.security.KeyStore;

public interface KeyStoreImporter {

 public void importPrivateKey(KeyStore keyStore, String keyPassword) throws GeneralSecurityException;
}


import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;

public interface KeyStoreExporter {

 public Key exportKey(KeyStore keyStore, String keyPassword) throws GeneralSecurityException;
}


So, how to use them? Example as below:


//Key generation and key import
KeyPair keyPair = generateRSAKeyPair();
final Certificate[] certs = CryptoUtils.generateCertificate(keyPair);

RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
final RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();

logger.debug("[generateAndStoreRSAKeyPair] pubKey={},privKey={}", publicKey.getClass(), privateKey.getClass());

keyStoreTemplate.saveToKeyStore(new KeyStoreImporter() {
 @Override
 public void importPrivateKey(KeyStore ks, String keyPassword) throws KeyStoreException {
  ks.setKeyEntry(alias, privateKey, keyPassword.toCharArray(), certs);
 }
});


//Method to get an RSA public key
public RSAPublicKey getRSAPublicKey(final String alias) throws BusinessException {

 return (RSAPublicKey)keyStoreTemplate.getFromKeyStore(new KeyStoreExporter() {
  @Override
  public Key exportKey(KeyStore keyStore, @SuppressWarnings("unused") String keyPassword) throws GeneralSecurityException {
   Certificate cert = keyStore.getCertificate(alias);
   RSAPublicKey publicKey = (RSAPublicKey)cert.getPublicKey();
   return publicKey;
  }
 });
}


//Method to get a secret key
public SecretKey getSecretKey(final String alias) throws BusinessException {

 return (SecretKey)keyStoreTemplate.getFromKeyStore(new KeyStoreExporter() {
  @Override
  public Key exportKey(KeyStore keyStore, String keyPassword) throws GeneralSecurityException {
   SecretKey secretKey = (SecretKey)keyStore.getKey(alias, keyPassword.toCharArray());
   return secretKey;
  }
 });
}

Thursday, March 14, 2013

Cryptography Using JCA - Services In Providers


The Java Cryptography Architecture (JCA) is an extensible framework that enables you to use perform cryptographic operations. JCA also promotes implementation independence (program should not care about who's providing the cryptographic service) and implementation interoperability (program should not be tied to a specific provider of a particular cryptographic service).

JCA allows numerous cryptographic services e.g. ciphers, key generators, message digests to be bundled up in a java.security.Provider class, and registered declaratively in a special file (java.security) or programmatically via the java.security.Security class (method 'addProvider').

Although JCA is a standard, different JDKs implement JCA differently. Between Sun/Oracle and IBM JDKs, the IBM JDK is sort of more 'orderly' than Oracle's. For instance, IBM's uber provider (com.ibm.crypto.provider.IBMJCE) implements the following keystore formats: JCEKS, PKCS12KS (PKCS12), JKS. Oracle JDK 'spreads' the keystore format implementations into the following providers:

  • sun.security.provider.Sun - JKS
  • com.sun.crypto.provider.SunJCE - JCEKS
  • com.sun.net.ssl.internal.ssl.Provider - PKCS12
Despite the popular recommendation to write applications that do not point to a specific Provider class, there are some use cases that require an application/program to know exactly what services a Provider class is offering. This requirement becomes more prevalent when supporting multiple application servers that may be tightly coupled with a particular JDK e.g. WebSphere bundled with IBM JDK. I usually use Tomcat+Oracle JDK for development (more lightweight, faster), but my testing/production setup is WebSphere+IBM JDK. To further complicate matters, my project needs the use of a hardware security module (HSM) which uses the JCA API via the provider class com.ncipher.provider.km.nCipherKM. So, when I am at home (without access to the HSM), I would want to continue writing code but at least get the codes tested on a JDK provider. I can then switch to use the nCipherKM provider for another round of unit testing before committing the code to source control.

The usual assumption is that one Provider class is enough e.g. IBMJCE for IBM JDKs, SunJCE for Oracle JDKs. So the usual solution is to implement a class that specifies one provider, using reflection to avoid compile errors due to "Class Not Found":


//For nShield HSM
Class c = Class.forName("com.ncipher.provider.km.nCipherKM");
Provider provider = (Provider)c.newInstance();

//For Oracle JDK
Class c = Class.forName("com.sun.crypto.provider.SunJCE");
Provider provider = (Provider)c.newInstance();

//For IBM JDK
Class c = Class.forName("com.ibm.crypto.provider.IBMJCE");
Provider provider = (Provider)c.newInstance();



This design was OK, until I encountered a NoSuchAlgorithmException error running some unit test cases on Oracle JDK. And the algorithm I was using is RSA, a common algorithm! How can this be, the documentation says that RSA is supported! The same test cases worked fine on IBM JDK.

Upon further investigation, I realised that much to my dismay, the SunJCE provider does not have an implementation for the KeyPairGenerator service for RSA. An implementation however is found in the provider class sun.security.rsa.SunRsaSign. So the assumption of "1 provider to provide them all" is broken. But thanks to JCA's open API, a Provider object can be passed in when requesting for a Service instance e.g.


KeyGenerator kgen = KeyGenerator.getInstance("AES", provider);


To help with my inspection of the various Provider objects, I've furnished a JUnit test to pretty-print out the various services of each registered Provider instance in a JDK.


package org.gizmo.jca;

import java.security.Provider;
import java.security.Provider.Service;
import java.security.Security;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.crypto.KeyGenerator;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;

public class CryptoTests {

 @Test
 public void testBouncyCastleProvider() throws Exception {
  Provider p = new BouncyCastleProvider();
  String info = p.getInfo();
  System.out.println(p.getClass() + " - " + info);
  printServices(p);
 }
 
 @Test
 public void testProviders() throws Exception {
  
  Provider[] providers = Security.getProviders();
  for(Provider p : providers) {
   String info = p.getInfo();
   System.out.println(p.getClass() + " - " + info);
   printServices(p);
  }
 }
 
 private void printServices(Provider p) {
  SortedSet<Service> services = new TreeSet<Service>(new ProviderServiceComparator());
  services.addAll(p.getServices());
  
  for(Service service : services) {
   String algo = service.getAlgorithm();
   System.out.println("==> Service: " + service.getType() + " - " + algo);
  }
 }

 /**
  * This is to sort the various Services to make it easier on the eyes...
  */
 private class ProviderServiceComparator implements Comparator<Service> {

  @Override
  public int compare(Service object1, Service object2) {
   String s1 = object1.getType() + object1.getAlgorithm();
   String s2 = object2.getType() + object2.getAlgorithm();;

   return s1.compareTo(s2);
  }

 }
}


Anyway, if the algorithms you use are common and strong enough for your needs, the BouncyCastle provider can be used. It works well across JDKs (tested against IBM & Oracle). BouncyCastle does not support JKS or JCEKS keystore formats, but if you are not fussy, the BC keystore format works just fine. BouncyCastle is also open source and can be freely included in your applications.

Tip: JKS keystores cannot store SecretKeys. You can try it as your homework :)

Hope this post will enlighten you to explore JCA further, or at least be aware of the pitfalls of 'blissful ignorance' when working with JCA.