iOS and Mac OSX - Full Database Encryption with SQLCipher
This SQLCipher Static Library package provides full database encryption for iOS and Mac OS X applications. These pre-compiled binaries are easily imported into an XCode project to be statically linked to an application. This provides the quickest integration and fastest application builds:
- The iOS library is built for armv6 and armv7 iOS architectures and also supports the i386 iOS Simulator
- The OS X library is built for i386 and x86_64 architectures
Both versions include statically linked OpenSSL libcrypto, so you only need to include a single package in the project.
SQLCipher static libraries for iOS and Mac OSX are "commercial edition" software that can be purchased directly from the Zetetic Store. Licensed software is delivered immediately upon payment.
Buy SQLCipher for iOS Now » Buy SQLCipher for Mac OS X Now »
Important Note: SQLCipher can also be integrated with iOS and Mac OS X applications using the free Community Edition software. This approach is described in a separate tutorial. However, the commercial edition static libraries have some significant advantages:
- easier to setup, saving many steps in project configuration
- pre-built with a modern version of OpenSSL, avoiding another external dependency
- much faster for each build cycle because the library doesn't need to be built from scratch on each compile (build time can be up to 95% faster with the static libraries)
The remainder of this document provides a practical example of how to integrate SQLCipher in an XCode project.
Add Files to Project
This tutorial assumes that XCode is already installed and that a basic application is already setup. The sqlcipher-static-ios.zip package and an iOS project are used as an example, but the directions are exactly same for the sqlcipher-static-osx.zip package and an OS X project!
First, our binary distribution directly into your project's folder. In Finder, navigate to the sqlcipher-static-ios.zip file you received and unzip it by double-clicking on the zip file. Next, open up your iOS project's directory in Finder and manually copy the unzipped sqlcipher-static-ios folder into it.

Next, we'll add the static library file itself to your project's References. Open up your project in Xcode, and once it's loaded, right-click (or control-click) on your project's icon in the Project Navigator (Command+1) and select 'Add Files to ""...'

Select libsqlcipher.a, and make sure that "Copy items into destination group's folder" is not selected, since the file is now already inside your project's folder.

The file should now appear in the Project Navigator:

Header Search Paths
To ensure that Xcode uses the sqlite3.h file from our distribution, as well as the correct OpenSSL headers, you will modify the Header Search Paths setting on your project's Target. Click on your project icon to bring up the project settings, select your app's target in the list, and select the Build Settings pane. In the search field, type in "Header Search Paths." Double-click on the field under the target column and add the following path: sqlcipher-static-ios/include:

Other C Flags
You will have to edit one other setting on your target to ensure the SQLCipher builds correctly—"Other C Flags." Start typing "Other C Flags" into the search field until the setting appears, double click to edit it, and in the pop-up add the following value: -DSQLITE_HAS_CODEC

Build and Run!
Click on the Run button at the top of Xcode, and be amazed at how fast the project compiles and fires up!
SQLCipherSpeed tests the performance of SQLCipher, you can use it yourself to try this out, but be sure you remove the sqlcipher.xcodeproj and openssl.xcodeproj references from the Project Navigator.
Integration Code
Now that the SQLCipher library is incorporated into the project you can start using the system immediately. Telling SQLCipher to encrypt a database is as easy as opening a database and using the sqlite3_key function.
#import <sqlite3.h>
...
NSString *databasePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent: @"sqlcipher.db"];
sqlite3 *db;
if (sqlite3_open([databasePath UTF8String], &db) == SQLITE_OK) {
const char* key = [@"BIGSecret" UTF8String];
sqlite3_key(db, key, strlen(key));
if (sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
// password is correct, or, database has been initialized
} else {
// incorrect password!
}
sqlite3_close(db);
}
Note that it is also possible to initialize the database by calling PRAGMA key, ass follows, but this is not recommended unless code is in place to handle potential escaping issues.
PRAGMA key = 'BIGSecret';
The call to sqlite3_key or "PRAGMA key" should occur as the first operation after opening the database. In most cases SQLCipher uses PBKDF2, a salted and iterated key derivation function, to obtain the encryption key. Alternately, an application can tell SQLCipher to use a specific binary key in blob notation (note that SQLCipher requires exactly 256 bits of key material), i.e.
PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";
Once the key is set SQLCipher will automatically encrypt all data in the database! Note that if you don't set a key then SQLCipher will operate identically to a standard SQLite database.
After the application is wired up to use SQLCipher, take a peek at the resulting data files to make sure everything is in order. An ordinary SQLite database will look something like the following under hexdump. Note that the file type, schema, and data are clearly readable.
% hexdump -C plaintext.db
00000000 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 |SQLite format 3.|
00000010 04 00 01 01 00 40 20 20 00 00 00 04 00 00 00 00 |.....@ ........|
...
000003b0 00 00 00 00 24 02 06 17 11 11 01 35 74 61 62 6c |....$......5tabl|
000003c0 65 74 32 74 32 03 43 52 45 41 54 45 20 54 41 42 |et2t2.CREATE TAB|
000003d0 4c 45 20 74 32 28 61 2c 62 29 24 01 06 17 11 11 |LE t2(a,b)$.....|
000003e0 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 |.5tablet1t1.CREA|
000003f0 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29 |TE TABLE t1(a,b)|
...
000007d0 00 00 00 14 02 03 01 2d 02 74 77 6f 20 66 6f 72 |.......-.two for|
000007e0 20 74 68 65 20 73 68 6f 77 15 01 03 01 2f 01 6f | the show..../.o|
000007f0 6e 65 20 66 6f 72 20 74 68 65 20 6d 6f 6e 65 79 |ne for the money|
Fire up the SQLCipher application in simulator and look for the application database files under /Users/sjlombardo/Library/Application Support/iPhone Simulator/5.0/Applications/<Instance ID>/Documents. Try running hexdump on the application database. With SQLCipher the output should looks completely random, with no discerning characteristics at all.
% hexdump -C sqlcipher.db
00000000 1b 31 3c e3 aa 71 ae 39 6d 06 f6 21 63 85 a6 ae |.1<..q.9m..!c...|
00000010 ca 70 91 3e f5 a5 03 e5 b3 32 67 2e 82 18 97 5a |.p.>.....2g....Z|
00000020 34 d8 65 95 eb 17 10 47 a7 5e 23 20 21 21 d4 d1 |4.e....G.^# !!..|
...
000007d0 af e8 21 ea 0d 4f 44 fe 15 b7 c2 94 7b ee ca 0b |..!..OD.....{...|
000007e0 29 8b 72 93 1d 21 e9 91 d4 3c 99 fc aa 64 d2 55 |).r..!...<...d.U|
000007f0 d5 e9 3f 91 18 a9 c5 4b 25 cb 84 86 82 0a 08 7f |..?....K%.......|
00000800
Troubleshooting
If you see build errors complaining about missing symbols (e.g. undefined symbols "_EVP_CIPHER_CTX_cleanup" or "_sqlite3_key"), you may have a common linking problem due to incorrect project setup or cached derived data. Try each of following steps to resolve the issue:
- Go to the Target -> Build Phases -> Link Binary with Libraries section, and make sure that neither libsqlite3.dylib or libsqlite3.0.dylib are listed. If they are, remove them, leaving only the libsqlcipher.a
- Ensure that
-DSQLITE_HAS_CODECis included in the "Other C Flags" setting for your Target - Open finder, navigate to ~/Library/Developer/Xcode/DerivedData/ and delete all the files under the derived data folder in your home directory
Finally, Run a Product -> Clean on your project and try to rebuild. The link errors should no longer appear.
Get SQLCipher Binaries for iOS and Mac OS X
These packages can be purchased directly from the Zetetic Store and licensed software is delivered immediately upon payment.
Buy SQLCipher for iOS Now » Buy SQLCipher for Mac OS X Now »

