Tuesday, September 10, 2013

Encrypt URL parameters using AES in Java using Spring MVC

Why on earth would you want to do this...  Well, this is one of those crazy requirements that come up with limited resources.

Well.. I do charity work for a 5013C, which has limited resources and one of the requirements they asked of me was to be able to embed data in a static url..  Normally, this would just be a request parameter and my day would proceed on in a rather bland fashion.

This time, it was unique in that some of the data was sensitive (It applied a discount code to the price of a few items) - so manipulating that data would be impactful to the operational integrity of the application. So, how do you secure data when all you have is a url string (SSL and Post options were off the table as this was being embedded as a link in numerous other websites).

So, I decided to use a json payload and encrypt it using AES.. base64 encode it, urlEncode it... and dump that value along with the initial vector into the url as params. It was a rather small payload with only a few sensitive fields, so it was effective, yet crude..

I would be interested in knowing how others would handle this using only a url String making a RESTful call to a server.

The basic requirements:

1. It must be a RESTful url..  All the data is contained in the url.
2. Flat files and database stores are out of the question.. no way to persist data (This was the kicker for me)
3. It has to be embeddable and a direct call.. no middle man url's, etc..

I hope someone reads this and presents a graceful answer.. I don't feel that mine was the best answer, but given my tools in my toolbox.. I didn't see a better way.

Below is the code that does the lifting..  It's fairly straight forward:

Encrypting:
1. The object is serialized to a byte[]
2. Create a Cipher and a random initial vector
3. Hash the key using SHA-256 then trim it to 128-bit for the key
4. Base64 encode the encrypted value
5. Encode the Base64 value to a url friendly format
6. Return the encoded values to include as request parameters in the link

The link will look something like:
http://www.foo.com/view?a=PM90%2B0mzlDLpK5NKlG7CP5lgafMzn5qsrHulCRLR9ZkXnq9L5v7SMuEp%2BPWFtdNR1UxHGw%2Fxh7NzZSPtwSKNRCmQe8fNEMkJJuI4lJ3uvg0DrbI9xXALFZpUs6gAbO7SW5UCeHd6SYWMSWnM9agH9Mw13yfiCKNdiWPiW9j%2BhJa0J5lPraqF1x8srdfm48JaMEg1IaHtRLXukH3VjPTN8sGRUE8nzsu%2BGIyRLaHlXNKt5nZ4wAKtd9Dtfmwe4bgX4k7aEUpaYr90nCU67a%2BxX0NtDB6z7n5lkCQ7bQTNzSA%3D&b=Jux7I3tv%2Ff6HXXFrGOozZA%3D%3D

Decrypting:
1. We decode the request param from Base64 into the raw format. (The container takes care of the url encoding conversion.. so this is not a factor in TC Server)
2. Decode the intial vector value from Base64 into the raw format.
3. Configure the cipher using the secret and the initial vector that was passed in the url
4. Decrypt the encrypted data
5. Serialize the decrypted bytes back into the expected object

All this work.. due to a few limitations. Bleh.. But, it was a fun little traversal in cryptography in Java.

Below is a code sample setup to run in Spring MVC:

6 comments:

  1. Thanks a lot Shane. I did a lot of googling and this is what works for me :)

    ReplyDelete
  2. Hello Shane, great post.
    Only one observation: Base64 includes the character '+' in its charset. So, you can get an encrypted value with a '+' inside. If the URLDecoder is used in the decrypt phase, it will transform the '+' into a space, "breaking" the value.
    To solve this, it should be used Base64.encodeBase64URLSafe() that copes with '+' and '/' chars.

    ReplyDelete
  3. can you please make a live example of how it will actually works in spring mvc , getting the parameters from the form and then encrypt it and then decrypt them to show the next form .

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. where is the code?
    ----------------------------------------------------
    Below is a code sample setup to run in Spring MVC

    ReplyDelete