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.

8 Responses to Encrypting Data in AIR

  1. Campbell says:

    Lol I wrote the same thing two days ago, and found that you can save a lot of space (I was using localstored object with its size limits) by doing a ByteArray.compress();I also went a bit looser on the definition of the Config and just made it a proxy object, using the proxy methods to handle the writes. Cheers for sharing this 🙂

  2. Hi Christian,I’m a huge fan of AIR. But this “encrypted” bit in AIR local storage sounds flaky to me. In fact, like the root causes of many serious application security issues that are so prevalent today, I would argue that this encryption feature will give application developers a false sense of security, leading to widespread insecurities in the future.Let me explain my point of view. Please feel free to correct me if I’m wrong.You say the data in the encrypted local store is associated with a specific OS user, AIR application ID, and publisher ID. Therefore, I assume your motivation is to create privacy/isolation for this data.Now if the AIR runtime does enforce this degree of data privacy/isolation why encrypt it as well? I can only assume you guys consider this to be a solution to any attempts from outside the AIR runtime (for example by a native application on the host) to read the raw local data store data. The rationale perhaps is since the raw data is encrypted, the external party will not be able to decrypt the data without the necessary key(s).There’s a huge gaping hole in this logic. You guys use the host OS APIs to encrypt the data in the first place! These APIs can be trivially subverted (with mere user privileges on some platforms to perform code injection into the AIR process). Therefore the encryption could either be entirely bypassed or a copy of the data you’re encrypting could be made.So what if you implement the encryption algorithms in the AIR runtime itself? Again, this will add one more layer of obfuscation but the result is the same. AIR process can be manipulated to achieve the same ends as above.The only way to reasonably do the encryption/decryption to protect against attacks that originate from outside the AIR runtime is if the encryption was performed remotely and the decryption keys are never stored on the client side, but just the encrypted data (in the local data store).So perhaps it’s a lot more reasonable to provide a server side encryption/decryption service code for PHP/Java/.NET etc., and an AIR API to access these services over HTTPS such that the developers can go the extra mile should they require greater data protection.Otherwise, unwittingly, you guys might be creating a serious “false sense of security” trap here…CheersNishad

  3. Nishad,I’m not a security expert, but I’ll do my best to address your concerns.You mention: These APIs can be trivially subverted (with mere user privileges on some platforms to perform code injection into the AIR process).I’m not sure I’d call injecting code into the AIR process entirely trivial. Although the term “trivial” is subjective, so for the sake of argument, let’s say it is. I don’t think AIR applications are any more or less vulnerable than other types of applications. Your data is as secure as DPAPI/Keychain. In fact, it may be more secure since you need more than just the user’s password to decrypt them. The app and publisher IDs are also used as keys.At the end of the day, it’s up to the end user to protect his/her machine, and not install malicious applications. We try hard to protect against malicious processes, but if someone installs an application that is determined to steal data, it can do so in any number of ways (such as key logging, which AIR obviously can’t do anything about).As far as letting a server do your encryption/decryption, that has its own sets of challenges. You then have one central place where all credentials are stored (and can therefore be stolen). Of course, it’s up to you to keep your sever safe, but I would argue that it’s also up to the end user to keep his/her computer safe.The other issue with the server approach is that the end user then has to be prompted for a key, password, or pass phrase to do the decryption. The whole idea of DPAPI/keychain is to avoid that experience. The obvious answer is to store the users pass phrase to provide a better experience, but then of course, you’re back to square one.Christian

  4. Ed Rowe says:

    Nishad,The goal of the encryption is to prevent access by anybody who does not know the user’s OS-level password, not to protect against rogue processes as you suggest. For example, if the credentials were left in the clear and my laptop was stolen, even without knowing my password you could read them (unless encryption was enabled at the OS level, which is uncommon). Similar scenarios can occur when multiple users share the same computer – one user could read another’s credentials if they were unencrypted unless a) the filesystem supports user-level access permissions (FAT32 does not) and b) the file is stored in a permission controlled location and c) permissions have been setup appropriately. As a developer, the use of EncryptedLocalStore improves security by making sure that what is stored in it is only available to the current user.Ed RoweAdobe AIR Team

  5. christmas gifts says:

    I like the keystring idea that Linux uses, where your passwords are all stored in a key ring that allows access to your applications through one password.In other words, I only need the password into the keyring (which we can make secure in many other ways) and you have access into all your applications. This idea can be used a little. In terms of the fact that they may need to enter in their main system key, and then only answer a very easy passphrase or question when accesssing other applications. But I think you’ve got some great ideas here, that’s for sure!

  6. Sebastian says:

    Hello, very interesting thread. What about the concept of protecting your data so that the user [or any company who installs the AIR app] can read it? This would imply building a decryption system within AIR that the user couldn’t get to if they start reverse engineering the FLEX/AIR file.Is this something one can do easily?Is there any way to protect data locally on the desktop so that only the AIR application can decode it?Thank you kindly, Sebastian.

  7. Dan Rolander says:

    Good stuff. Thanks for doing this. I use DPAPI now for a few apps, but it will be really nice now to have a cross platform solution for protecting passwords. Hopefully when you have a Linux AIR client you’ll be able to extend this API to that platform as well.I think some of your commenters are missing the point. These are well known Operating System APIs for protected storage. Adobe didn’t invent a new security solution, they just built wrappers for the two APIs and gave them a nice common interface.

  8. Flüge says:

    Dan,you are right, it isn´t quite a new invention, but surely an advance in security. I am a little displeased from hearing about it so late, but use it since two weeks.