导语:
SQLite 是一个轻量级的、开源的关系型数据库,是目前移动平台(如 iOS、Android)数据库的最佳选择。然而免费版的 SQLite 是不支持加密的(官网下的默认就是免费版的) ,这就导致了存储在 SQLite 中的数据很容易被人查看到,不法分子可能会利用数据库表结构及内容字段分析我们的应用,进而发起攻击。出于安全的考虑,我们当然要对数据库文件进行加密。
数据库加密
-
加密方式的选择
对数据库加密主要有两种方式:将内容加密后再存入数据库中
这种方式使用简单,只需要在入库和出库时将字段加解密即可,但数据库的表结构信息依然能被查看到。并且对内容加密后,搜索查看数据库中的内容都比较麻烦。对数据库文件直接进行加密
这种方式是比较安全的加密方式,目前已知的 SQLite 加密方案基本上都是通过这种方式实现的。
加密工具的选择
目前已知的对 SQLite 加密的工具主要有「SQLite Encryption Extension (SEE)」、「SQLiteEncrypt」、「SQLiteCrypt」、「SQLCipher」,但是这里面仅有 SQLCipher 有免费版本。
这样看来,开源的 SQLCipher 是 SQLite 加密的最佳选择了。
简单介绍下,SQLCipher 是一个开源的,基于免费版 SQLite 的加密数据库。它采用 256-bit AES 进行加密,主要的接口和 SQLite 相同,另外增加了一些加解密相关的接口。
数据库迁移
可能已发布的 APP 使用的是未加密的 SQLite 版本,因此当用户覆盖安装时,就需要对未加密的数据库进行加密。而 SQLCipher 出于效率考虑,它是基于页进行加密的,因此需要对原有数据库中的内容进行迁移。
根据 SQLCipher 官方文档, 其本身已经提供了对数据库迁移的支持,主要就是sqlcipher_export
函数。
需要注意的是:
由于检测数据库是否加密比较困难,因为数据库尚未打开,没办法调用数据库提供的方法进行检测(事实上可以采用检测 SQLite 数据库文件的前 100 个字节中的信息来检测是否加密)。因此最好是采用检测旧数据库文件是否存在的方式来决定是否对数据库进行迁移。如果旧数据库存在则按照迁移流程进行,若不存在则按照加密流程进行即可。
密码安全
数据库加密及迁移问题都解决了,但是如何保障所用密码的安全呢?
由于 SQLCipher 在设计之初就将密码的管理与数据库加密的实现区分开来,因为这样能提供更好的灵活性,但同时也意味着使用者需要负责密码的管理。官网 FAQ 中建议如下:1. 密码内容应该直接来自用户,且不应该存储在设备上。2. 密码内容不应该直接硬编码在程序中。
事实上,若要密码真正的可靠安全,需要采用类似 HTTPS 的一套流程,存在与服务器的交互且实现复杂。
其实可以采用简单的密码算法,配合密码更新机制来解决这个问题。基本方案如下:
采用「用户ID + 固定字符(如 abc123 ) + 加密算法版本号」进行 MD5 生成密码。然后在数据库文件名包含「用户ID」和「加密算法版本号」,这样只要拿到数据库文件就可以算出该数据库的密码,算法相对简单且使用方便。
为了防止数据库密码泄露或者被破解,可以对数据库密码增加更新策略,SQLCipher 本身已经提供了更新密码的接口。决定是否需要更新密码可以通过判断数据库名称中的「加密算法版本号」实现。若「加密算法版本号」与当前 APP 中内置的不一致,则执行新的密码生成算法(如替换固定字符为 xyz888 等),随后再调用 SQLCipher 更新密码的接口即可。
参考:
(完)