Friday, March 1, 2013

Encrypting string resources when using Android library projects.

When you're using an Android library project as the base code for multiple projects, it's handy to rely on resource overrides for configuration parameters.  For example, you could use a strings resource file that points to different URLS, etc.  While doing this is quite handy, you must also consider that resource files are very easy to extract using apktool, so if you are concerned about keeping any of this configuration data secure, you're going to have to take some extra precautions.

For a very basic obfuscation method you can just base64 the content and put it in a string resource.   I wouldn't recommend this alone, as any reasonably competent person can decode the string.  The nice thing about base64 is that it's output charset doesn't contain apostrophes or double-quotes (by design).  Because of this, base64 encoded data does not need to be escaped when used in a string resource.

For a better real-world scenario, let's assume that we have an application where we want to enable in-app billing, and to do so we need to be able to store the license key from our application in a reasonably secure fashion.  At the same time, we'd still like to leverage the convenience of resource overrides to store the license keys in our sub-projects that rely on a core android library project.

Our high level strategy will be to do the following.
  1. Encrypt our application license key (obtained via the Google Developer Console) using a hardcoded encryption key (think password).
  2. Base64 the encrypted 'cipher' text.
  3. Use this encrypted/base64 encoded value in our strings resource file.
Here's some sample code to help accomplish these tasks, just note that we will only use this code to generate our encrypted and base64 encoded license key before storing it in a resources file.  This is a one time activity.  And this should go without saying, but REMEMBER TO CHANGE THE VALUES IN keyBytes

Once you have the string encrypted/encoded as such and placed in your strings file, you simply need to decrypt it when needed.  Here's some example code :

Making it even more secure.

Since it's hard to get around hardcoding your secret key (the keyBytes in our sample code) using this strategy, it would be naive to assume this is 100% foolproof.  A persistent minded individual could still decompile your app, discover the byte array you used for encryption, and then reverse the entire process.  Your job is to make this as difficult as you can reasonably make it. You could store your key in multiple byte arrays and combine them when needed, for instance.  I won't go into specific methods here, but the point is to be creative. Using a code obfuscation tool such as proguard will help, or at the very least use non-obvious/misleading method names to perform these operations.