加密你的SQLite

轉自王中周的我的博客html

 

關於SQLiteios

SQLite是一個輕量的、跨平臺的、開源的數據庫引擎,它的在讀寫效率、消耗總量、延遲時間和總體簡單性上具備的優越性,使其成爲移動平臺數據庫的最佳解決方案(如iOS、Android)。
 
然而免費版的SQLite有一個致命缺點:不支持加密。這就致使存儲在SQLite中的數據能夠被任何人用任何文本編輯器查看到。好比國內某團購iOS客戶端的DB緩存數據就盡收眼底: 
 
SQLite加密方式
對數據庫加密的思路有兩種:
 
1. 將內容加密後再寫入數據庫
這種方式使用簡單,在入庫/出庫只須要將字段作對應的加解密操做便可,必定程度上解決了將數據赤裸裸暴露的問題。
 
不過這種方式並非完全的加密,由於數據庫的表結構等信息仍是能被查看到。另外寫入數據庫的內容加密後,搜索也是個問題。
 
2. 對數據庫文件加密
將整個數據庫整個文件加密,這種方式基本上能解決數據庫的信息安全問題。目前已有的SQLite加密基本都是經過這種方式實現的。
 
SQLite加密工具
目前網上查詢到iOS平臺可用的SQLite加密工具備如下幾種:
 
事實上SQLite有加解密接口,只是免費版本沒有實現而已。而SQLite Encryption Extension (SEE)是SQLite的加密版本,提供如下加密方式:
  1. RC4 
  2. AES-128 in OFB mode 
  3. AES-128 in CCM mode 
  4. AES-256 in OFB mode 
 
SQLite Encryption Extension (SEE)版本是收費的。
 
使用AES加密,其原理是實現了開源免費版SQLite沒有實現的加密相關接口。
 
SQLiteEncrypt是收費的。
 
使用256-bit AES加密,其原理和 SQLiteEncrypt同樣,都是實現了SQLite的加密相關接口。
 
SQLiteCrypt也是收費的。
 
首先須要說明的是,SQLCipher是徹底開源的,代碼託管在 Github上。
 
SQLCipher使用256-bit AES加密,因爲其基於免費版的SQLite,主要的加密接口和SQLite是相同的,但也增長了一些本身的接口,詳情見 這裏
 
SQLCipher分爲收費版本和免費版本,官網介紹的區別爲:
asier 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)
 
 
只是集成起來更簡單,不用再添加OpenSSL依賴庫,並且編譯速度更快,從功能上來講沒有任何區別。僅僅爲了上述一點便利去花費幾百美刀,對於我等苦逼RD來講太不值了,還好有一個免費版本。
 
鑑於上述SQLite加密工具中,只有SQLCiper有免費版本,下面將將着重介紹下SQLCiper。
 
在項目中使用SQLCipher
在項目中集成免費版的SQLCipher略顯複雜,還好官網以圖文的方式介紹的很是詳細,集成過程請參考 官網教程
 
使用SQLCipher初始化數據庫
下面這段代碼來自官網,其做用是使用SQLCipher建立一個新的加密數據庫,或者打開一個使用SQLCipher建立的數據庫。
  1. NSString *databasePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
  2.                               stringByAppendingPathComponent: @"cipher.db"]; 
  3.     sqlite3 *db; 
  4.     if (sqlite3_open([databasePath UTF8String], &db) == SQLITE_OK) { 
  5.         const char* key = [@"BIGSecret" UTF8String]; 
  6.         sqlite3_key(db, key, strlen(key)); 
  7.         int result = sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL); 
  8.         if (result == SQLITE_OK) { 
  9.             NSLog(@"password is correct, or, database has been initialized"); 
  10.         } else { 
  11.             NSLog(@"incorrect password! errCode:%d",result); 
  12.         } 
  13.          
  14.         sqlite3_close(db); 
  15.     } 
 
須要注意的是,在使用sqlite3_open打開或建立一個數據庫,在對數據庫作任何其它操做以前,都必須先使用sqlite3_key輸入密碼,不然會致使數據庫操做失敗,報出sqlite錯誤碼SQLITE_NOTADB。
 
在sqlite3_open打開數據庫成功,並且用sqlite3_key輸入密碼之後,就能夠正常的對數據庫進行增、刪、改、查等操做了。
 
使用SQLCipher加密已存在的數據庫
SQLCipher提供了sqlcipher_export()函數,該函數能夠方便的對一個普通數據庫導入到SQLCipher加密加密的數據庫中,操做方式以下:
  1. $ ./sqlcipher plaintext.db  
  2. sqlite> ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'testkey';  
  3. sqlite> SELECT sqlcipher_export('encrypted');  
  4. sqlite> DETACH DATABASE encrypted;  
 
解除使用SQLCipher加密的數據庫密碼
sqlcipher_export()函數一樣能夠將SQLCipher加密後的數據庫內容導入到未加密的數據庫中,從而實現解密,操做方式以下:
  1. $ ./sqlcipher encrypted.db  
  2. sqlite> PRAGMA key = 'testkey';  
  3. sqlite> ATTACH DATABASE 'plaintext.db' AS plaintext KEY '';  -- empty key will disable encryption 
  4. sqlite> SELECT sqlcipher_export('plaintext');  
  5. sqlite> DETACH DATABASE plaintext;  
 
整體來講,SQLCipher是一個使用方便,靈活性高的數據庫加密工具。
 
另外,我寫了個 SQLCipherDemo工程放到了 CSDN上,有須要的同窗請自行下載。
 
參考文檔
 
 
 
 
相關文章
相關標籤/搜索