Encrypting Data in AIR

AIR applications often need to store credentials. Many web services out there require authentication, which means that AIR applications need a secure way to store sensitive data. I first ran into this issue when I wrote Salsa, an Amazon S3 client. Salsa needs the end user’s public and private access keys for signing requests, but since both keys are long arbitrary strings that are almost impossible to memorize, I couldn’t ask the user to enter them each time they wanted to use the application. And for obvious reasons, I couldn’t store them in plain text. I needed a way to persist the user’s credentials in way that would not allow other users or processes to access them.

This was back in days of AIR beta 1. The only option I had at the time was to encrypt the credentials myself using a pass phrase provided by the end user. Each time the user started the application, therefore, I had to prompt them for their pass phrase which I’d use to decrypt the public and private keys. If they lost their pass phrase, they had to reenter their public and private keys, as well as enter a new pass phrase. From a usability perspective, this was not the experience I was after.

But then along with AIR beta 2 came the flash.data.EncryptedLocalStore API. There have been some small changes in M6 (the upcoming beta 3), but it’s essentially the same. The EncryptedLocalStore APIs use DPAPI on Windows and the Keychain on Mac to encrypt arbitrary data and associate it with a specific OS user, AIR application ID, and publisher ID. That means applications can encrypt and store data that only the current user and the current application can decrypt. And the best part is that it’s extremely easy to use:

// Writing encrypted information
var passwordBytes:ByteArray = new ByteArray();
passwordBytes.writeUTFBytes("secretPassword");
EncryptedLocalStore.setItem("password", passwordBytes);

// Reading encrypted information
var passwordBytes:ByteArray = EncryptedLocalStore.getItem("password");
var password:String = passwordBytes.readUTFBytes(passwordBytes.length);

To make using the EncryptedLocalStore even easier, my team has written a Preferences API on top of it which makes it extremely easy for applications to store either encrypted or non-encrypted user preferences using any serializable data type.

Whether you use our Preferences library or the EncryptedLocalStore directly, I really think the ease with which sensitive data can be encrypted and decrypted will encourage developers to build secure and user-friendly AIR applications.