Secure Data Persistence with AIR 3

AIR 3 offers two new capabilities that can make data persistence much more secure than what was possible with previous versions of AIR. If your AIR application persists information like credentials or sensitive relational data that must remain secure, this article is for you.

flash.crypto.generateRandomBytes()

The new flash.crypto.generateRandomBytes function provides a way to generate far more random data than was previously possible. As you probably already know, functions like Math.random are known as pseudorandom number generators because they rely on relatively small sets of initial data (like timestamps). Bytes generated in such a manner are insufficient for use as encryption keys because if the random number generation algorithm is known (and you should always assume that it is), and the mechanism for seeding it is known and constrained, it isn’t hard for an attacker to guess the encryption key and gain access to your data.

The new generateRandomBytes function uses a much more random (and therefore, much more secure) method for generating random bytes. Rather than implementing our own algorithm, the runtime uses the underlying operating system’s random byte generation function. The table below shows which function is used on each platform:

Operating System Function
Windows CryptGenRandom()
Mac OS X /dev/random
Linux /dev/random
Android /dev/urandom
iOS SecRandomCopyBytes()

The natural question at this point is what makes the operating systems’ random byte generation implementations so secure — or, put another way, how is the OS able to generate random data which is more cryptographically secure than Math.random? The answer is something called an entropy pool. An entropy pool is essentially a collection of randomness. When a process needs random bytes, they can be taken from the entropy pool through one of the functions listed above, and when a process believes it has random data, it can choose to add those bytes to the entropy pool. Processes can obtain random data in several ways:

  • Hardware jitter (deviations caused by things like electromagnetic interference or thermal noise).
  • Mouse movements and/or the time between keystrokes.
  • Unpredictable hardware events like disk head seek times, or network traffic.
  • A hardware random number generator.

(Now is a good time to state that it’s probably more correct to say that an entropy pool contains unguessable data as opposed to truly random data, but in the world of encryption, the two amount to essentially the same thing.)

So now that you have access to unguessable bytes, what can you do with them to make your data more secure? The most obvious use for the new generateRandomBytes function is probably the creation of encryption keys. The database implementation embedded inside of the AIR runtime supports encrypted database files, and the quality of the encryption is largely based on the quality of your encryption key. The generateRandomBytes function gives you a cryptographically secure way to generate an encryption key, and the EncryptedLocalStore API gives you a secure method for storing it (more on this below). Other uses of the generateRandomBytes function include generating session identifiers, GUIDs, and salt to be used in hashes (salt is additional data added to the data you want to hash which makes looking the hash up in rainbow table much less feasible).

Mobile Encrypted Local Store

Update (11/3/2011): If you’re having trouble getting ELS to work in the iOS emulator or in “fast packaging” mode, add the following to your compiler arguments: -swf-version=13

A second feature in AIR 3 which can make data persistence more secure is the introduction of the mobile EncryptedLocalStore (ELS) API. ELS has been available for the desktop profile since 1.0, but AIR 3 is the first version which makes it available on mobile.

ELS provides a secure storage mechanism implemented by the underlying operating system. On Windows, ELS uses DPAPI, and on OS X, ELS uses Keychain services.

The new mobile implementations of ELS require some additional explanation. On iOS, ELS uses Keychain services just as it does on OS X, however Android does not provide a encrypted storage service for the runtime to leverage. Data is therefore "sandboxed" rather than encrypted. In other words, it is stored in a secure, isolated location (inaccessible to other processes), but since the data isn’t actually encrypted, if an attacker has access to the physical device, or if a user has rooted his or her device, it is possible for the data to be compromised. According to the internal ELS specification:

On Android, ELS can guarantee that on a non-rooted device in the hands of an authorized user, ELS data of an AIR application will not be accessible/modifiable by any other application (AIR or native) running on the device.

It’s possible that Android will provide a more secure storage service in the future, and we can simply swap out our implementation, however for the time being, it’s worth noting that the Android implementation lacks the additional step of encryption on top of isolation.

So what kinds of data should mobile developers store with ELS? The same data that you would store in desktop applications. Namely:

  • Encryption keys (the sequence of random bytes obtained through the generateRandomBytes function).
  • Account credentials. If you want to store users’ credentials so they don’t have to enter them every time they use your app, ELS is the correct API to use.
  • Salts for hashes. Once you’ve salted and hashed something like a password, you need to be able to securely persist the salt for future comparisons.

Summary

If you just need to generate random numbers for something like a game, you should stick to using Math.random. In fact, on some platforms, the generateRandomBytes function could temporarily block if the entropy pool has been entirely drained which means you don’t want to pull large amounts of data from it in an endless loop. Rather, generateRandomBytes should be reserved for generating unguessable cryptographically secure random data for things like encryption and session keys, GUIDs, and salts for hashes.

Whenever you need to store sensitive information like credentials, encryption keys, or salts, you should always use the EncryptedLocalStore APIs. Since they are now supported everywhere, you can use them in a completely cross-platform manner.

Whether you’re updating an existing application that needs to persist data securely, or building an entirely new one, I strongly recommend that you use the new best practices made possible in AIR 3.

11 Responses to Secure Data Persistence with AIR 3

  1. Pingback: Article: AIR3 secure data persistance | biskero

  2. Cliff Hall says:

    I’m pretty sure ELS is not supported on iPad with AIR 3 / Flex 4.5.1. I’ve updated my FlashBuilder utilities/ipa_packager folder with adt.jar and aot/* from the AIR 3 SDK.

    But when I deploy to the ipad and try to access the ELS, I get the “ELS Not Supported in this version” error in the debugger.

    I’ve searched the net high and low and found no confirmation that this works anywhere.

    • Cliff Hall says:

      UPDATE:
      EncryptedLocalStore.isSupported == false in the iOS simulator
      EncryptedLocalStore.isSupported == false on iOS with “Fast Packaging”
      EncryptedLocalStore.isSupported == true on iOS when exported as release build.

      This is a serious bullet to the head for debugging an app that uses ELS. You have no choice but to mock all your ELS access if you want to debug your app.

      BTW Christian, I’m not saying you’re responsible for the problem or complaining to you like tech support, it’s just that this seems to be one of the main articles that come up when researching this problem, so I hope it saves somebody some time.

  3. Nate says:

    Hi Christian. How do you create a GUID using the new secure stuff? I’ve been looking around but I can’t figure it out :(.

  4. Christian Cantrell says:

    @Cliff: Thanks for the notice. This is definitely a bug, and it’s already being discussed internally. ELS is supposed to work in the simulator, and with both fast and release packaging. I’ll post again when I have an idea of when the fix will be released.

  5. Cliff Hall says:

    Thanks Christian. Your tip of adding -swf-version=13 to the compiler arguments fixed the problem.

  6. Arun says:

    ELS was not working on Android 3.2 device nor simulator (with Flex Builder 4.5.1, AIR 3.0).

    Now that I added the compiler argument “swf-version=13” ELS supported property is true. Thank you!!

    Shouldn’t this functionality work without any magic compiler flags? What are the side-effects of this flag? Will this flag become obsolete in the future? Will this flag restrict other newer features (whenever they are released)?

    The thing that troubles me is that each time I have trouble with AIR, I need to google for some blog or site which tends to suggest some “fix”.

  7. Arun says:

    Just an FYI.

    With the aforementioned compiler argument “-swf-version=13” ELS works on Android, but when the device is rotated, the screen display gets all out of whack; sometimes it shows portrait mode when in landscape, and vice-versa, i.e. the views get all chopped off and the action bars get messy, etc. Removing the “-swf-version=13” flag brings the application (screen) behavior back to normal.

    Thanks.