SQLite學習筆記(十)&&加密


     隨着移動互聯網的發展,手機使用越來越廣泛,sqlite作為手機端存儲的一種解決方案,使用也非常普遍。但是sqlite本身安全特性卻比較弱,比如不支持用戶權限,只要能獲取到數據庫文件就能進行訪問;另外也沒有加密功能,任何人獲取到文件后,就可以查到明文數據。這使得大家對於sqlite又愛又不敢用,畢竟用戶的隱私是非常重要的。Sqlite分為開源版本和收費版,收費的版本是支持加密的,只不過需要付2000刀的技術支持費。當然,由於sqlite本身是開源的,業內有很多產品對sqlite增加了加密功能,比如wxsqlite,sqlcipher等。因此想免費使用加密版本的sqlite也不是不可以,但前提是使用過程遇到問題,一定要能hold住,因為免費的東西不一定是穩定的。廢話少說,本文主要討論兩個問題, 1.自己如何實現sqlite的加密功能,2.如何使用加密的sqlite。

加密算法選擇

     要實現加密,首先需要選擇一種主流、高效、安全的加密算法,對於手機端和嵌入式設備,還要加上一條簡單的原則。加密算法主要分為對稱加密算法和非對稱加密算法,對於文本加密一般采用對稱加密,而對於秘鑰的管理則采用非對稱加密。目前主流的對稱加密算法有DES,AES,RC系列,TEA系列, Blowfish等,非對稱加密算法有RSA、Diffie-Hellman等。本人對幾種常見的對稱加密算法進行了測試,綜合起來AES和XXTEA算法性能最好,XXTEA的優勢在於實現非常簡單,代碼不到100行,在端設備上也是一種優勢。另外,騰訊一直在使用TEA系列算法作為它的通訊加密和本地存儲加密,用實踐證明了TEA系列算法的可靠性和安全性。下圖是AES算法和XXTEA算法的一些測試數據,僅供參考。XXTEA-256和XXTEA-64,分別表示塊大小是256個INT和64個INT。通過測試讀寫200M數據的時間來評估算法的優劣,每個數據通過測試5次取平均值。

 

不加密

AES

XXTEA-256

XXTEA-64

寫操作

7879.3ms

10283.6ms

10577.3ms

10649.4ms

讀操作

315.69ms

3681.4ms

3527ms

3598ms

 

上層應用加密

     選擇好加密算法,那么要實現加密功能了。有童鞋會問,為啥一定要在sqlite內部實現加密,上層應用加密不是一樣OK嗎?這個確實可以。很多開發語言都自帶了加密庫函數,直接調用即可。寫入數據時進行加密,讀出數據時再進行解密。但這種方式主要有以下幾個缺點:

  1. 對於加密的數據列,無法使用索引,雖然可以用等值查詢,但對於范圍查詢則無能為力。而且所有類型需要設計為BLOB類型,來存儲密文。
  2. 雖然可以對數據列進行加密,但表的元數據無法加密。

所以,總地來說,應用層是一種解決方案,但對開發者不太友好。

sqlite自身加密

     從原理上來看,加入加密模塊功能也相對簡單,在寫入數據塊前,調用加密模塊進行數據塊加密,然后寫入文件;而在讀取數據塊時,先調用加密模塊解密,然后加載到緩存。加密模塊(紅色標注)在整個sqlite實現框架的位置如下圖。

 

實現層面,我們要做的工作主要包括三部分,實現加密算法,然后將加密接口與sqlite關聯起來,最后在合適的位置(讀寫文件),調用加/解密接口完成加密解密工作。由於sqlite自身已經預留了加解密接口,因此第3部分的工作已經幫我們做了,我們只需要實現第1和第2部分工作。核心接口如下:

    1.sqlite3CodecAttach 

含義:調用sqlite3PagerSetCodec 將加密接口與sqlite的pager模塊關聯

    2.xxxCodec

含義:自己定義的加密接口,輸入參數是(page_no,讀寫模式),將指定page加、解密。

    3.sqlite3_key

含義:設置數據庫密鑰,sqlite3_open后調用該接口。對於非加密庫,若調用該接口,會導致后續訪問數據報錯。

Error: file is encrypted or is not a database

    4.sqlite3_rekey

含義:修改數據庫密鑰,這個接口會遍歷數據庫中的所有頁,然后用新密鑰對頁進行加密,寫入文件。若將新密鑰設置為NULL,則可以將加密庫變為普通庫。

    5.sqlite3_activate_see

       sqlite3CodecGetKey

這兩個接口沒有實際作用,可以實現一個空函數,保證能編譯通過就行。

加密sqlite使用

如果順利,我們現在已經有了一個包含加密功能的sqlite了,那么如何使用?下面主要列了一些常見的場景。

   1.如何判斷一個db文件是否加密

$sqlite3 ./data/test.db

sqlite> .tables Error: file is encrypted or is not a database 

sqlite> pragma key='123456' ;

sqlite> .tables

Error: file is encrypted or is not a database 

對於加密的db文件,如果沒有執行pragma key=xxx命令直接執行,則會報錯。假設密碼是 123456,報錯后,重新執行pragma key命令,然后執行.tables,這時候依舊報錯。這個主要是因為密鑰在連接創建時初始化,所以對於加密數據庫,需要執行的第一條命令是pragma key=xxx 

    2.導出加密文件數據

$sqlite3 ./data/test.db // 打開加密數據庫文件test.db

sqlite> pragma key='123456';   // 設置秘鑰   

sqlite> .output aaa.sql //將輸出重定向到文件aaa.sql

sqlite> .dump //導出數據庫

sqlite> .exit   這樣aaa.sql中包含了test.db中數據庫的明文內容。

    3.解密加密數據庫

$sqlite3 ./data/test.db

sqlite> pragma key='123456'

sqlite> pragma rekey='';  //設置密鑰為空,則將密文數據庫解密。   

 

//解密后可以直接打開數據庫   

$sqlite3 ./data/test.db

sqlite> .tables

  • orders  t1  user  

sqlite> .exit 

參考文檔

https://en.wikipedia.org/wiki/XXTEA


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM