Smarter ideas worth writing about.

Encrypted Data Persistence on Mobile Devices

In today’s technological world the trend is shifting towards mobile now more than ever. Most employees at enterprise companies have mobile devices that are used daily, whether that is a company owned device or a personal device. The shift leads us to start moving heavy, all-inclusive, desktop applications into smaller, more focused applications. One of the major concerns with this is the shift of data from a fixed location machine to a mobile device.

Background

Mobile platforms have a level of security provided by the operating system (OS) that a developer can take advantage of to protect local storage. However, when using persistent stores on mobile devices sqlite, or a local database(db), is used for storage. By default sqlite is not encrypted. Its only form of protection is that it is sandboxed from other applications. Using the OS security, for example on iOS, we can store db files with security permissions that allow the OS to encrypt the data when the device is locked. This must be done by the developer and is only active while the device has a passcode enabled. On Android there is a restricted space that you can store data in that is only accessible by that application. However, it does lack the ability to specify per file attributes. If a device is jailbroken or rooted, that is allow/bypass device security, all bets are off in terms of securing data using the OS methods.

With data being shifted to devices we need a way to ensure data is encrypted that is stored in db files. This is where sqlcipher comes to the rescue. “SQLCipher is a specialized build of the excellent SQLite db that performs transparent and on-the-fly encryption. Using SQLCipher, an application uses the standard SQLite API to manipulate tables using SQL. Behind the scenes the library silently manages the security aspects, making sure that data pages are encrypted and decrypted as they are written to and read from storage.”

Example

Using iOS (Objective-C) as an example we will see what changes when using sqlcipher to encrypt the db.

Traditionally we create a persistent store for our db in iOS, this is done numerous ways but we will stick with the default Apple Core Data/ sqlite implementation.

 

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

The bolded code in the above example above is the traditional template boilerplate code Apple provides for creating a persistent store coordinator. NOTE: the code for the persistantStoreCoordinator is removed for length consideration. This will create a db file that is stored in the documents directory. The documents directory is a user readable area of an application, this means we could pull this db off and open it in another application. Another note to be aware of is that documents stored in the documents directory are backed up to iCloud. This meaning that the encrypted database would be backed up. However, to read the database you would still need the encryption key.

If we pull that db created off we can run the hexdump tool on the db to view that it is not encrypted. We are able to see plaintext data in the db as well as read directly from the db file.

The Fix

Using the sqlcipher library with our project we can change a few lines of code and encrypt the entire database. We will need to add an Object-C sqlcipher wrapper to our project. For the sake of length a link, to the wrapper is here: https://github.com/project-imas/encrypted-core-data/tree/master/Incremental%20Store

Once we have sqlcipher built and linked against the project, imported the encrypted store wrapper, we can modify the persistent store line from the previous example.

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [EncryptedStore makeStore:[self managedObjectModel]:@"SOME_PASSWORD"];
    //NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

 

Sqlcipher uses a key as its means of encrypting data in the database. This key can be a string key or PBKDF2 (256 bit key) that is salted and integrated key derivation function to get the final encryption key. In the example above we have SOME__PASSWORD as our password. When the application runs, we still have access to pull the db from the device but when we try to access or hexdump the db we only see the encrypted data.

Wrap Up

Using sqlcipher we can further protect user data on the device in the enterprise setting, allowing sensitive data to be stored on a device with minimal fear that it will be decrypted without the proper key. There are two different versions of sqlcipher, the community edition and the commercial edition. The community version must be compiled manually and supports iOS/Mac OS X, Android, and PHP. While the commercial library offer some pre-compiled static libraries, it supports ADO.NET, PC libs for iOS/Mac OS X, Xamarin (iOS/Android) and Windows.

You can find more information about sqlcipher at: http://sqlcipher.net and https://github.com/sqlcipher/sqlcipher.

Share:

About The Author

Principal Consultant I
Eric is a Principal Developer in Cardinal's Cincinnati office who is focused on pushing the envelope technically and creatively in mobile application development.