IOS database encryption complete manual – FMDB+SQLCipher

This article describes how to encrypt the database file, based on FMDB+SQLCipher, marked the stepped pit, leaving the same drop into the pit of a small partner reference.

1, download support SQLCipher FMDB branch

FMDB official library address: https://github.com/ccgus/fmdb

SQLCipher official website: https://www.zetetic.net/sqlcipher/

The author made a support SQLCipher warehouse, save us a lot of time to compile and project configuration, thanks!

Modify Podfile:

take

Pod’FMDB’

Replace as

Pod’FMDB/SQLCipher’

Update the Pod can get support SQLCipher FMDB.

2, the use of encryption methods

(BOOL) setKey: (NSString*) key;

Method is very simple, the key is to use the location:

2.1, the direct use of FMDatabase

Each call

[db open]

Call once

2.2, the use of FMDatabaseQueue

call

(instancetype) databaseQueueWithPath: (NSString*) aPath

Is called once, for example:

Self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath] [self.dbQueue inDatabase:^ (FMDatabase*db) {
[db setKey:kDBEncryptedKey]}];

There is a pit: not every call – (void) inDatabase: (void (^) (FMDatabase*db)) when block
calls in the block – (BOOL) setKey: (NSString*) key
only need to call once when initializing the FMDatabaseQueue end, but also to ensure that the first call, or any database the operation is illegal!

3, non encrypted database < -> encrypted database

How to convert the existing non encrypted database to the encrypted database in the case of saving the data?

How to restore the encrypted database data to a non encrypted database?

Need to use the sqlcipher_export () method.

3.1, create a new database encryption

If the database to be created is brand new, call it directly in the above

– (BOOL) setKey: (NSString*) key

Encrypted database.

3.2, the existing non encrypted database into encrypted database

If your database is not encrypted, call the method described above

– (BOOL) setKey: (NSString*) key

It does not convert an existing database into an encrypted database.

Here is an example of a copy from SQLCipher:

Example 1: Encrypt a Plaintext Database
plaintext.db sqlite&gt ATTACH $./sqlcipher DATABASE’encrypted.db’AS encrypted KEY;’testkey’; sqlite> SELECT; sqlite> sqlcipher_export (‘encrypted’) DETACH DATABASE encrypted;

We only need to perform three SQL statements can be copied to the encrypted database encryption database, is not very simple? But there’s a pit:

1, sqlite> ATTACH DATABASE’encrypted.db’AS encrypted KEY’testkey’;’encrypted.db’in this sentence, the full path for creating encrypted database, not just the name of the database;
2, sqlite> SELECT sqlcipher_export (‘encrypted’); this sentence in’encrypted’, on behalf of a keyword!!! It is not the full path of the database to be created! Maybe it’s really too simple for me. 3, sqlite> DETACH DATABASE encrypted; yes, the encrypted is also a keyword

Use code package:

#define [email protected] “ABCDEFG”
NSString *encryptedDBPath “Your/DB/Path/encryptedDB.db” NSString = @ *plainttextDBPath @ = “Your/DB/Path/plainttextDB.db”
const char *sql [[NSString stringWithFormat:@ = “ATTACH DATABASE AS encrypted KEY’%@”%@’; encryptedDBPath, kDBEncryptedKey], UTF8String];
const char *exportSql = [[NSString stringWithFormat:@ SELECT sqlcipher_export (‘encrypted’); UTF8String] const char *detachSql”]; = “NSString” stringWithFormat:@ DETACH DATABASE encrypted; UTF8String] SQLite3 “]; *unencrypted_DB = NULL; if (sqlite3_open ([plainttextDBPath, UTF8String], & unencrypted_DB) {int RC ==SQLITE_OK); char *errmsg = NULL; RC = sqlite3_exec (unencrypted_DB, SQL, NULL, NULL, & errmsg; RC) =sqlite3_exec (unencrypted_DB, exportSql, NULL, NULL, & errmsg); RC =sqlite3_exec (unencrypted_DB, detachSql, NULL, NULL, & errmsg); sqlite3_close (unencrypted_DB);}

Else {sqlite3_close (unencrypted_DB); (NO NSAssert1, Failed to open database @ with message’%s’., sqlite3_errmsg (unencrypted_DB));}

Through the above code can be copied from a non encrypted database to retain a database of encrypted data, encrypted database generation remember to delete the old database.

3.3, the encrypted database into non encrypted database

Here’s an example of a copy from SQLCipher:

Example 2: Decrypt a SQLCipher database to a Plaintext Database
encrypted.db sqlite&gt PRAGMA $./sqlcipher; key =’testkey’; sqlite> ATTACH DATABASE’plaintext.db’ AS plaintext KEY empty key will ‘; — Disable encryption sqlite& gt; SELECT sqlcipher_export (‘plaintext’); sqlite&gt DETACH; DATABASE plaintext;

Remember the pit above:

‘plaintext.db’is to create the unencrypted full path data;
‘plaintext’ is the key, not the path is not a suffix to remove the name of the database;
plaintext is the key;

Use code package:

#define [email protected] “ABCDEFG”
NSString *encryptedDBPath “Your/DB/Path/encryptedDB.db” NSString = @ *plaintextDBPath @ = “Your/DB/Path/plainttextDB.db” const char [[NSStringstringWithFormat:@ “PRAGMA *sql = key =’%@’; kDBEncryptedKey] UTF8String];
const, char *attachSql = [[NSString stringWithFormat:@ ATTACH DATABASE AS plaintext KEY’%@’ ‘; plaintextDBPath] UTF8String]; const char,” *exportSql = [[NSStringstringWithFormat:@ “SELECT sqlcipher_export (‘plaintext’)] UTF8String]; const char;” *detachSql = [[NSStringstringWithFormat:@ “DETACH DATABASE plaintext; UTF8String] sqlite3*encrypted_DB =NULL;”]; if (sqlite3_open ([encryptedDBPathUTF8String], & encrypted_DB) {==SQLITE_OK) int RC; char *errmsg = NULL; RC = sqlite3_exec (encrypted_DB, SQL, NULL, NULL, & errmsg); RC =sqlite3_exec (encrypted_DB, attachSql, NULL, NULL, & errmsg); RC =sqlite3_exec (encrypted_DB, exportSql, NULL, NULL, & errmsg); RC =sqlite3_exec (encrypted_DB, detachSql, NULL, NULL, & errmsg); sqlite3_close (encrypted_DB
);}

Else {sqlite3_close (encrypted_DB); (NO NSAssert1, Failed to open database @ with message’%s’., sqlite3_errmsg (encrypted_DB));}

The above code can be used to restore the encrypted database to an unencrypted database.

The pit: a converted database in addition to retain the data, and did not keep the previous database additional information, such as userVersion, remember the old database userVersion is assigned to the new database, or the database upgrade may be in trouble!

The key code here, we need to be based on individual freedom, I will not write, because lazy.