很多人不太担心SQLite
数据库的数据安全性问题,
因为存入SQLite
的数据一般都是客户端软件自己存储的,
哪些数据该落地,哪些数据不该落地,
是客户端的职责,应该由客户端识别并区分。
敏感数据丢了,不应该责怪数据库。
然而有些场景比较特殊,客户端没办法区分哪些数据是敏感数据,哪些数据不是敏感数据。
比如:聊天软件(IM),
由于要查询历史消息,所以聊天数据都得落地(从服务器访问慢,且服务器压力大)。
但谁也不知道历史消息里哪句话是敏感的,哪句话是不敏感的。
所以负责安全得领导就会提要求:加密保护客户端数据库。
有很多技术方案用以保护Sqlite数据库文件,今天我只讲一个方案,也是最好的方案: SQLite Encryption Extension
:
SQLite Encryption Extensionwww.sqlite.org/see/doc/trunk/www/readme.wiki
这个方案允许开发者向SQLite
写入加密的内容(存入数据库的是密文),从SQLite
中读取加密的内容(读到内存中的是明文),
也就是说,如果客户端内存暴露了,那数据还是不安全的,但这已经足够了。
我们知道SQLite
是可以创建内存数据库的:sqlite3.connect(':memory:')
。
根据上面的道理,这个方案也不会对内存数据库加密。它只对数据库文件加密。
不过数据库文件的安全性还是非常不错的,
主数据库、回滚日志和WAL文件都是被保护的,
加密算法也有好几种可供选择(如下所示:),官方推荐用AES-256加密。
AES-256 in OFB mode
AES-128 in OFB mode
AES-128 in CCM mode
RC4 with security enhancements (legacy only)
每个加密方式对应一个(或多个)c 代码文件(SQLite
是c写的)
sqlite3-see-aes256-openssl.c
sqlite3-see-aes256-cryptoapi.c
sqlite3-see-aes256-ofb.c
sqlite3-see-cccrypt.c
sqlite3-see-aes128-ofb.c
sqlite3-see-aes128-ccm.c
sqlite3-see.c
sqlite3-rc4.c
sqlite3-xor.c
这些代码文件与开源的sqlite3.c
在能力上是一致的,
拿到这些文件之后,你完全可以把其中一个重命名为sqlite3.c
再编译,
这样你就可以在你的客户端中使用SQLite
的数据保护能力了。
打开(连接)数据库的API还是原来的:sqlite3_open()
。
不过在打开数据库之后,你应该马上传入密钥,才能访问加密的数据库。
cpp
int sqlite3_key_v2(
sqlite3 *db, /* The connection from sqlite3_open() */
const char *zDbName, /* Which ATTACHed database to key */
const void *pKey, /* The key */
int nKey /* Number of bytes in the key */
);
如果你的项目不是C/C++开发的,那么你可以通过这种方式传入密钥
cpp
db.pragma('key=your-secret-key'); //Node.js
值得一提的是,你可以使用编译的程序,访问未加密的数据库
(如果你的客户端有两个数据库,一个加密,一个未加密,你不用集成两套SQLite
代码)
访问未加密的数据库,只要把pKey
设置成NULL
或者nKey
设置成0
即可。
看到这里,你是不是想用这个方案啦?
哈哈,这个方案是收费的:2000美金买断(不算贵吧?)
让那个提出需求的老板去交钱吧:
Encryption Extensionsqlite.org/purchase/see
别走开,还有一点有趣的东西,
我们知道SQLite
是可以编译成动态链接库的,
假设你交了钱之后,拿到了代码,编译成了动态链接库,
那岂不是任何人只要拿到你这个动态链接库就可以不用付钱使用这个方案啦?
不是的。
在你使用这个动态链接库之前,你要激活它一下:
cpp
sqlite3_activate_see("7bb07b8d471d642e"); //这个字符串,在你交钱之后,就会得到
不激活,你就用不了这个动态链接库。
点赞支持,这样我会尽快写第二篇,第二篇里会介绍免费的方案(应该跟你想的那个方案不一样哦)。