Wednesday, October 27, 2010

Tutorial: iPhone SQLite Encryption With SQLCipher



Your Ad Here



Mobile devices are notoriously difficult to secure. With a small footprint it is dangerously easy to leave your phone in the back of a taxi, or forget to pick it up from a table after dinner at a restaurant. iPhone and iPod Touch devices are no exception – most applications store their data in an easily readable format. Anyone with access to your device can browse through your personal information. Even worse, since the devices back up to your computer, any knowledgeable person with access to your workstation can read your data as well.
This is balanced by immense convenience. An iPhone makes a perfect digital wallet: a single device with all your important information literally at your fingertips. When we set out to write Strip, our iPhone Password Manager and Data Vault, we wanted to build a system that we could trust to store Passwords, Credit Card Numbers, Passport Identifiers, SSNs and bank account information. Most of the other applications in the App store used undocumented encryption or weaker field level security. We wanted to encrypt EVERY bit of Strip’s data on the device. Naturally the ideal approach would be to have the encryption managed transparently, so Strip didn’t need to know about the details.
Enter SQLCipher, a specialized build of the excellent SQLite database 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. SQLCipher uses the widely trusted and peer-reviewed OpenSSL library for all cryptographic functions.
SQLite is already the predominant API for persistent data storage on the iPhone so the upside for development is obvious. As a programmer you work with a stable and well documented API. All security concerns are cleanly decoupled from application code and managed by the underlying framework. The framework code of the SQLCipher and OpenSSL projects are both open source, so users can be confident that an application isn’t using insecure or proprietary security code.
Using SQLCipher in an iPhone application is straightforward once you setup your project properly. The easiest way to integrate SQLCipher into an application is to use XCode project references as described here.

Get OpenSSL
SQLCipher relies on OpenSSL for several encryption requirements including the AES-256 algorithm, pseudo random number generation, and PBKDF2 key derivation. OpenSSL isn’t a framework that is usable directly on the iPhone so we will setup our project to build and link against it as a static library.
Navigate to the OpenSSL download page. Download the source file of the latest stable version (0.9.8k as of this writing) and extract it to a folder on your system. Make a note of the source directory path for later.
OpenSSL can be a tricky system to compile properly from source. It’s even more complex when you’re dealing with multiple target architectures, targeting i386 for the simulator but armv6 for a device. Luckily we’ve built a handy XCode project template to make it easy called openssl-xcode. The project actually relies on the OpenSSL configure and make system to build the libraries. However, it automatically detects the appropriate build settings for architecture (i386, ppc, arv6), build tools, and SDK. This makes it ideal for inclusion in an iPhone project. Just git clone or download openssl-xcode from GitHub and move the openssl.xcodeproj file into the OpenSSL source directory.

Get SQLCipher
SQLCipher is a standalone package that includes the entire SQLite source distribution. You can git clone or download the latest version from the SQLCipher repository on GitHub. Again, make note of the source directory path you use for later in the setup process.

XCode Setup
SQLCipher uses project references to manage build dependencies and static linking. In order to allow linking you must setup your XCode environment to use a central build location. We will also need to configure Source Trees OpenSSL and SQLCipher respectively.
  1. Open XCode, Choose the XCode Menu, and then Preferences.
  2. On the Building tab, Change the “Place Build Products In” to “Customized location” and pick a location for the build directory.

  1. Switch to the Source Tree tab.
  2. Add a SQLCIPHER_SRC that references the path to the SQLCipher sourcecode
  3. Add a OPENSSL_SRC to reference the path to the OpenSSL sourcecode


Project Setup
Now that we have XCode global preferences setup we will move on to the project configuration.

Open your XCode application project, and click on the top level Project item. Hit option-command-a to add a resource. Navigate to the OpenSSL directory and choose the openssl.xcodeproj to add the reference. When the add resource window comes up make sure that “Copy items” is not checked, and add it to the appropriate target. Repeat the same, this time choose the sqlcipher.xcodeproj file in SQLCipher source directory.
Let’s change the Path Types as a convenience to multi-developer teams. Using paths relative to the Source Trees we defined will allow each developer to place the SQLCipher and OpenSSL in any locations and the build will still work.

  1. Hit option-i on the sqlcipher.xcodeproj reference and change the Path Type to “Relative to SQLCIPHER_SRC”.
  2. Hit option-i on the openssl.xcodeproj reference and change the Path Type to “Relative to OPENSSL_SRC”
  3. Hit option-command-a to add another resource
Now we will add build dependencies to ensure that the SQLCipher is compiled before the application code. Open the Info panel for your Application Target and Choose the General Tab. We will add two dependencies, one for OpenSSL crypto, and one for SQLCipher.

Then switch to the Build tab to add our source paths to the include directories to make relevant header files available. Make sure that the Configuration is set to “All Configurations”. Look for the “Header Search Paths” setting and add references to $(SQLCIPHER_SRC) and $(OPENSSL_SRC). Check “recursive” on both.

Finally, we will tell XCode to link against the built libraries. Expand the sqlcipher and openssl .xcodeproj references and select libsqlcipher.a and libcrypto.a. Drag and drop them on “Link Binary With Libraries” under your application target.


Building SQLCipher
At this point you should be able to build your XCode project without errors. Note that the first time you build your application for a particular architecture (Simulator for instance), it will take much longer than usual. This is because SQLCipher and OpenSSL are compiled from source for the specific architecture. You can keep track of the status under Build Results. Subsequent builds for the same platform will be much quicker since the libraries don’t need to be recompiled.

In Code
Now that you’ve incorporated the SQLCipher library into your project you can start using the system immediately. Telling SQLCipher to encrypt a database is as easy as opening a database and using “PRAGMA key” or the sqlite3_key function.
#import 

...
sqlite3 *db;
if (sqlite3_open(@"/path/to/database", &db) == SQLITE_OK) {
   sqlite3_exec(db, "PRAGMA key = 'BIGsecret', NULL, NULL, NULL);

   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!
   }
}
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, can tell SQLCipher to use a specific binary key in blob notation (note that you must provide exactly 256 bits of key material):
PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";
Once the key is set SQLCipher will automatically encrypt all data in the database! If you don’t set a key then SQLCipher will operate identically to a standard SQLite database.
Note: In the interest of brevity and clarity this section demonstrates the use of the API to set a passphrase and an encryption key using a static value. In a real application the passphrase or key data should be collected from an external source, like a “Secure” UITextField, and then passed to SQLCipher. An application should never hard-code its key, as this would be very easy to crack.

Verify
After your application is wired up to use SQLCipher you should take a quick 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.
new-host-2:sqlcipher sjlombardo$ 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 your SQLCipher application in simulator you can look for your database files under /Users//Library/Application Support/iPhone Simulator/User/Applications//Documents. Try running hexdump on your application database. With SQLCipher you should get output that looks completely random, with no discerning characteristics at all:
new-host-2:Documents sjlombardo$ hexdump -C encrypted.db
00000000  84 d1 36 18 eb b5 82 90  c4 70 0d ee 43 cb 61 87  |.?6.?..?p.?C?a.|
00000010  91 42 3c cd 55 24 ab c6  c4 1d c6 67 b4 e3 96 bb  |.B00000020  8e df fa bc c3 9c 92 8a  4e 40 59 6f b5 95 f3 80  |.????...N@Yo?.?.|
...
00000bd0  91 16 9e 89 d9 4e ac f7  1c c9 d1 d7 aa bb a7 51  |....?N??.??ת??Q|
00000be0  dc 77 5c 6c de c6 d3 be  43 49 48 3e f3 02 94 a9  |?w\l??ӾCIH>?..?|
00000bf0  8e 99 ee 28 23 43 ab a4  97 cd 63 42 8a 8e 7c c6  |..?(#C??.?cB..|?|
00000c00
Conclusion
SQLCipher is an easy way to incorporate full database encryption into an iPhone application. For more information on SQLCipher and the underlying security features please check out the SQLCipher project site. To see it in action please try Strip and Strip Lite in the iTunes App Store!

1 comment:

  1. Can you please update it for iPhone4 using XCode4.X.?

    ReplyDelete

 
Submit Express Inc.Search Engine Optimization Services