Thursday, September 22, 2011

AES and Java: Part the Third

So, in review, I needed to be able to encrypt a string using AES.

  • I started with a simple test to see if I could get the original string back after encrypting it.
  • The next step was to actually try hooking up the Java Cryptography classes to do the heavy lifting.
  • In this installment I'll clean up my current solution and extend it just a bit to be more generally useful.
Between last time and this, I extracted a class AESEncryptor, and removed some of the duplication. The constructor initializes both the encryptor and decryptor that are then used by the encrypt and decrypt functions.

And I expanded the test case to be a bit more readable. This also has the benefit of making more of the intermediate data visible if debugging is necessary.

So, am I done or is there another test that comes to mind?
Well, you may have noticed we have a bit of a problem here. The encryption key and vector are embedded in the constructor. Since a new key is generated each time an AESEncryptor object is created, I can't actually encrypt anything that someone else can successfully decrypt. While this approach may result in securely encrypted data, it lacks a bit of usefulness.

What test can I write that will advance my solution. I think that if I can get the same ciphertext out of two different AESEncryptor objects I'll be making some progress. So here is my new test:
And when I run the test I get a failure (as expected):
org.junit.ComparisonFailure: Expected :QXaIz4zs1ATJBkIEceLKE+Ad9gR35TYNyHZrsDgi1eo= Actual :JgbV3qcM6rdN0aPFKqPK7VBN5YhxfU8exzyM4+S3ZBY=

Looking at the way I initialize the Cipher instances, it looks like I need to pass in the byte array for the key and the byte array for the vector. Since I want to use the same key value across different tests, I'll move the key creation (and the population of the vector) to the test class. Furthermore, I want every test on that class to use the same values, so I'll initialize these arrays in an @BeforeClass method.

And moving those initializations to the test removes some of the code from the AESEncryptor constructor:

Am I done yet?
I don't think so. Passing byte arrays around can be problematic. It would probably be better to take in a string for the initialization values. And given what we learned in the course of researching the previous step we should probably pass in a base64 encoded string.

And in light of that change here is the final test class:

I think that is sufficient for this round of the problem.

No comments:

Post a Comment