Encryption, Codecs and Unit Tests in Grails

February 3, 2008 - 5 minute read -
grails encryption codecs

Certain data stored as plain text in a database is just asking for trouble these days. We hear too often about misplaced and stolen computers that contain databases full of Social Security numbers and other information that can lead to identity theft. We can help avoid these situations by encrypting those fields in a database so that if someone happens to get the data that they will have a difficult time getting the sensitive data.

Codecs

Grails provides a very good mechanism for this encryption in its Codec support. Codecs allow you to create encoders and decoders that become very easy to use in your application. Grails comes with a few useful ones built in to do things like Base64, URL, HTML, and Javascript Encoding.

Anywhere you have a string you can call the encodeAsCodecName or decodeCodecName to perform the encoding or decoding:

assert "apples & oranges " == "apples & oranges".encodeAsHTML()
assert "apples & oranges " == "apples & oranges".decodeHTML()

This is a nice, generally useful utility that can be used for any kind of string conversion really. There's nothing from stopping you from creating your encodeAsInteger or decodeShortDate if that's something you need a lot of in your application.

The basic format of a Codec is simple. You can create your new Codec in the grails-app/utils directory and it will be found automatically by Grails based on the naming convention.

class MyCodec {
    static encode = { str ->
        // Implement encoding here
    }
    static decode = { str ->
        // Implement decoding here
    }
}

Encryption Codec

In my case I wanted to create something to do encryption. Luckily this is not so hard with the javax.crypto classes. The crypto API is not the most straight forward to use in the world, but with a little bit of reading you can figure out how to encrypt and decrypt data without a lot of hassle. Basically what you see is a fairly simple encryption routine wrapped in the Grails Codec standard.

As you saw from previous example, the Codec standard is really simple, so all of the complexity here is really just the encryption code.

import javax.crypto.spec.SecretKeySpec
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import sun.misc.BASE64Encoder
import sun.misc.BASE64Decoder
import org.codehaus.groovy.grails.commons.ConfigurationHolder
/**
* Used for encrypting things to store in the database
*/
class SecureCodec {
    static BASE64Decoder decoder = new BASE64Decoder()
    static BASE64Encoder encoder = new BASE64Encoder()
    static encode = { str ->
        Cipher cipher = setupCipher(Cipher.ENCRYPT_MODE, getPassword())
        return encoder.encode(cipher.doFinal(str.getBytes()));
    }
    static decode = { str ->
        Cipher cipher = setupCipher(Cipher.DECRYPT_MODE, getPassword())
        return new String(cipher.doFinal(decoder.decodeBuffer(str)));
    }
    static getPassword() {
        return ConfigurationHolder.config.encryption.password
    }
    private static setupCipher(mode, password) {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // setup key
        byte[] keyBytes = new byte[16];
        byte[] b = password.getBytes("UTF-8");
        int len = b.length;
        if (len > keyBytes.length)
            len = keyBytes.length;
        System.arraycopy(b, 0, keyBytes, 0, len);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
        cipher.init(mode, keySpec, ivSpec);
        return cipher
    }
}

Another handy thing to notice is the ConfigurationHolder.config. This is the way to access application properties defined in Config.groovy. In a Domain class or a Controller you can get those values using grailsApplication.config but the grailsApplication variable is not available in Codecs or other classes. I use the Config.groovy to define an application specific secret to use for the encryption.

Testing Your Codec

Now to confirm that the code works we can write a Unit Tests. Encryption and Codecs are the perfect example of checking an Inverse Relationships to confirm the functionality of the Codec. Basically just encode it and decode it and compare the original value to the decoded value. If they match, it worked!

As a Unit Test

Outside the context of your running Grails application your Codec is just another Groovy class. Testing it in a Unit Test is easy though. You can just instantiate an instance of it and call the closures like they are methods.
class SecureCodecTests extends GroovyTestCase {
    void test_roundtrip_decodes_to_the_same_thing() {
        SecureCodec codec = new SecureCodec()
        def original = "secret"
        def encoded = codec.encode(original)
        def decoded = codec.decode(encoded)
        assert original != encoded
        assert encoded != decoded
        assert original == decoded
    }
}

As an Integration Test

If you want to be able to test it as it will be used in your Grails application though, you will need to run it as an integration test. The integration tests are loaded, instrumented and run just like they would be by the real Grails application. To do that, you just have to create the test under the tests/integration directory of your Grails application.
class SecureCodecTests extends GroovyTestCase {
    void test_roundtrip_decodes_to_the_same_thing() {
        def original = "secret"
        def encoded = original.encodeAsSecure()
        def decoded = encoded.decodeSecure()
        assert original != encoded
        assert encoded != decoded
        assert original == decoded
    }
}