iOS 使用FMDB SQLCipher給資料庫加密

來源:互聯網
上載者:User

標籤:

  關於SQLite,SQLCipher和FMDB

  SQLite是一個輕量的、跨平台的、開源的資料庫引擎,它的在讀寫效率、消耗總量、延遲時間和整體簡單性上具有的優越性,使其成為移動平台資料庫的最佳解決方案(如iOS、Android)。然而免費版的SQLite有一個致命缺點:不支援加密。這就導致儲存在SQLite中的資料可以被任何人用任何文字編輯器查看到。

  如果我們想要使得自己的資料庫加密,解決方案就是使用另一款開源的加密資料庫SQLCipher,SQLCipher使用256-bit AES加密,由於其基於免費版的SQLite,主要的加密介面和SQLite是相同的,當然也增加了一些自己的介面,如在建立和開啟資料庫時,給資料庫設定秘鑰之類的操作。

  FMDB是一個開源的類庫,它對sqlite資料庫操作進行了很不錯的封裝,而且也增加了對sqlcipher的支援,也就是說,我們不直接用sqlcihper也能完成加解密操作,而且FMDB在操作sqlite方面方便得多。現在的APP開發如果涉及到資料庫操作,FMDB基本上是首選。

  下面內容主要是針對一些在初期忽略了資料庫私密性,而到了中期需要讓資料庫進行升級加密的App的簡單方案介紹和代碼實現。如果讀者沒有使用FMDB,直接使用了sqlite,那本文也有一定參考性,只是關於SQLCipher的配置,並沒有介紹,因為雖然FDMB的加密也是使用SQLCipher,但是不需要進行配置的。

  具有加密功能的FMDB版本

  加密的FMDB其實是一個分支,也就是說,如果你需要替換FMDB。Github上關於該分支的安裝只提供了cocospod的安裝方式。

  Github上FMDB的地址:https://github.com/ccgus/fmdb

  

  舉個例子,如果你以前是如下寫的

pod ‘FMDB‘

  如果想換成有加密功能的,就改成

pod ‘FMDB/SQLCipher‘

  升級資料庫代碼實現

  得到對的版本後,我們需要在代碼裡做一些處理,讓舊資料庫升級。這裡升級包括兩點:

  1 是我們前面所說的,將資料庫加密。

  2 把舊資料庫的表和資料移轉到新資料庫中。

  sqlcipher的使用和sqlite沒有多大的區別,有一點值得注意便是每次當[dp open]成功後,需要給資料庫配上口令,即[db setKey:DB_SECRETKEY], DB_SECRETKEY是我們的一個自訂宏。這之後,我們才能讀出資料庫的內容。

FMDatabase *_db = [FMDatabase databaseWithPath:[cachePath stringByAppendingString:dbFileName]];if (![_db open]) {    _db = nil;    return;}else{    [_db setKey:DB_SECRETKEY];}

  然後我們需要判斷資料庫是否需要升級,當使用sqlchipher開啟用sqlite產生的來源資料庫時,[dp goodConnection]是為NO,即使上面[db open]操作是YES。

if(![_db goodConnection]){ //無效串連    [self upgradeDatabase:dbpath];}

  接下來,便是資料移轉,path是我們的來源資料庫路徑,假設我們的來源資料庫名字為DBName,changeDatabasePath即將我們的資料庫A改名為DBName.tmp,接下來便是,建立資料庫B,因為A在前面已經進行了改名為DBName.tmp,並且已經B將來就是我們要取代A的資料庫,所以此處的B名字便是DBName。最後將DBName.tmp的資料複製到DBName中,再刪除DBName.tmp,致此,我們的資料庫便升級完成了。

- (void)upgradeDatabase:(NSString *)path{    NSString *tmppath = [self changeDatabasePath:path];    if(tmppath){        const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE ‘%@‘ AS encrypted KEY ‘%@‘;",path,DB_SECRETKEY] UTF8String];                sqlite3 *unencrypted_DB;        if (sqlite3_open([tmppath UTF8String], &unencrypted_DB) == SQLITE_OK) {                        // Attach empty encrypted database to unencrypted database            sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, NULL);                        // export database            sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export(‘encrypted‘);", NULL, NULL, NULL);                        // Detach encrypted database            sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, NULL);                        sqlite3_close(unencrypted_DB);                        //delete tmp database            [self removeDatabasePath:tmppath];        }        else {            sqlite3_close(unencrypted_DB);            NSAssert1(NO, @"Failed to open database with message ‘%s‘.", sqlite3_errmsg(unencrypted_DB));        }    }}
- (NSString *)changeDatabasePath:(NSString *)path{    NSError * err = NULL;    NSFileManager * fm = [[NSFileManager alloc] init];    NSString *tmppath = [NSString stringWithFormat:@"%@.tmp",path];    BOOL result = [fm moveItemAtPath:path toPath:tmppath error:&err];    if(!result){        NSLog(@"Error: %@", err);        return nil;    }else{        return tmppath;    }}

  經過上面步驟,我們知道雖然sqlchipher是基於sqlite的,但到底還是不一樣的,我們沒辦法直接將sqlite的資料庫升級為sqlchipher,只能用sqlchipher建立一個資料庫,再重新寫入資料。  

  以上代碼僅僅是範例,各個App的資料存放區模型不盡相同,這裡我也沒辦法給出模板。雖然代碼不一定是適用的,但是在資料庫升級時,代碼執行的先後順序是肯定的:開啟資料庫open -> 設定秘鑰 setkey -> 查看串連 goodConnection -> 建立資料庫並遷移資料 upgrade。

iOS 使用FMDB SQLCipher給資料庫加密

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.