Using SQLCipher encryption with the Zumero iOS Framework
A developer recently asked us if, while using Zumero to sync application data to his devices, he could also encrypt that mobile data using SQLCipher.
The short answer: yes, and it’s easy. Zumero and SQLCipher work independently, unaware of each other; there’s no need to worry about SQLCipher during Zumero operations.
You’ll need to take care to set up your projects correctly, and add one SQL statement when opening a database. That’s it. Fully-encrypted local databases, happily synching with remote counterparts.
Setting Up Your Project
Create your XCode iOS project as you normally would. Don’t add any extra libraries at this time. In particular, don’t add sqlite3
.
Adding SQLCipher to your project
Using either SQLCipher Community Edition or SQLCipher Commercial Edition (easier to install, faster builds, up-to-date OpenSSL), install SQLCipher and add it to your project per the instructions.
Take a moment and Build your project; it’s easy to skip a step or get a search path wrong. I’ve heard. From a friend. Who’s totally not me.
Adding Zumero to your project
Download the Zumero Client SDK from our Dev Center, and unzip it to a non-temporary location. You’ll want to hang on to the libraries and documentation therein.
Drag ios/Zumero.Framework
from the SDK folder into your project’s “Frameworks” folder. No need to copy the files.
As mentioned in the Zumero iOS documentation, you’ll need to include iOS’s libz
and CFNetwork
libraries for Zumero to work properly.
When all is said and done, your library list will look something like:
…only with less red, since you will have already done your build troubleshooting. Good for you.
Build again, to confirm that Zumero is happily in place.
Encrypting your Zumero databases
Creating a new, encrypted database for Zumero takes one additional step: after opening the database with ZumeroDB::open
, you’ll need to issue a SQLite pragma
statement to set your encryption key. Use the same key every time you open the database.
NSError *err = nil;
BOOL ok = YES;
ZumeroDB *db = [[ZumeroDB alloc] initWithName:@"mydb"
folder:nil
host:@"http://localhost:8080"];
if (! [db exists])
ok = [db createDB:&err];
if (ok)
ok = [db open:&err];
if (ok)
{
NSString *sql = @"pragma key = 'secretword';";
ok = [cdb execSql:sql values:nil error:&err];
}
You’ll probably want to manage your keys a bit more carefully than that. Life’s so simple, here in sample-app land.
That’s it; your mobile database is encrypted, and can’t be read or modified without that same key. You can, and perhaps should, use different encryption keys for each mobile device. SQLCipher encryption does not apply to the Zumero sync traffic (although of course the communications themselves are encrypted).
Encrypting a plaintext database can’t be done in-place; you should be able to use sqlcipher_export, then replace the old database with the newly-encrypted copy.