對數據庫加密的思路
1.將內容加密后再寫入數據庫
這種方式使用簡單,在入庫/出庫只需要將字段做對應的加解密操作即可,一定程度上解決了將數據赤裸裸暴露的問題。
不過這種方式并不是徹底的加密,因為數據庫的表結構等信息還是能被查看到。另外寫入數據庫的內容加密后,搜索也是個問題。
2.對數據庫文件加密
將整個數據庫整個文件加密,這種方式基本上能解決數據庫的信息安全問題。目前已有的SQLite加密基本都是通過這種方式實現的。
使用SQLCipher加密SQLite
logo.jpg
SQLCipher是完全開源的,代碼托管在github上。SQLCipher使用256-bit AES加密,由于其基于免費版的SQLite,主要的加密接口和SQLite是相同的,但也增加了一些自己的接口。
SQLCipher分為收費版本和免費版本,差別只是集成起來更簡單,不用再添加OpenSSL依賴庫,而且編譯速度更快,從功能上來說沒有任何區別。
在項目中集成免費版的SQLCipher略顯復雜,還好官網以圖文的方式介紹的非常詳細,集成過程請參考官網教程。
使用SQLCipher初始化數據庫
在使用sqlite3_open打開或創建一個數據庫,在對數據庫做任何其它操作之前,都必須先使用sqlite3_key輸入密碼,否則會導致數據庫操作失敗,報出sqlite錯誤碼SQLITE_NOTADB。
在sqlite3_open打開數據庫成功,而且用sqlite3_key輸入密碼以后,就可以正常的對數據庫進行增、刪、改、查等操作了。
NSString *databasePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent: @"cipher.db"];
sqlite3 *db;
if (sqlite3_open([databasePath UTF8String], &db) == SQLITE_OK) {
const char* key = [@"abc123" UTF8String];
sqlite3_key(db, key, strlen(key));//注意此行
int result = sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL);
if (result == SQLITE_OK) {
NSLog(@"password is correct, or, database has been initialized");
[self initTablePerson:db];
[self insert:db];
[self query:db];
} else {
NSLog(@"incorrect password! errCode:%d",result);
}
sqlite3_close(db);
SQLCipher提供了sqlcipher_export()函數,該函數可以方便的對一個普通數據庫導入到SQLCipher加密加密的數據庫中。
sqlcipher_export()函數同樣可以將SQLCipher加密后的數據庫內容導入到未加密的數據庫中,從而實現解密。