首先iOS 8.3之前是直接可以拿到app沙盒里面的数据库的,之后应该也是有方法能拿到(待定,需要试试),所以还是需要对本地的数据库加密。
通用数据库加密方式:
1.对所有的数据加密
2.直接对数据库加密
第一个方法的话对于我们来说,数据库储存的内容极多,并且加密之后不便于我们自己查询,所以采用第二种方式。
集成:
之前因为小影直接用的是 pod'FMDB','~> 2.6',现在:pod'FMDB/SQLCipher','~> 2.7.2'
原理:
SQLite数据库加解密
首先需要从gitHub上下载SQLCipher的源码:
SQLCipher提供了几个命令用于加解密操作
加密:sqlcipher xiaoying.db
sqlite> ATTACH DATABASE 'xiaoyingEncrypt.db' AS xiaoying KEY '123456';
sqlite> SELECT sqlcipher_export('xiaoying');
sqlite> DETACH DATABASE xiaoying;
1.打开未加密的数据库
2.创建一个新的xiaoyingEncrypt.db附加到原数据库上
3.导出数据到新的数据库上
4.卸载新的数据库
解密:sqlcipher xiaoyingEncrypt.db
sqlite> PRAGMA key = '123456';
sqlite> ATTACH DATABASE 'xiaoying.db' AS xiaoyingEncrypt KEY '';
-- 空的密码就禁用密码了
sqlite> SELECT sqlcipher_export('xiaoyingEncrypt');
sqlite> DETACH DATABASE xiaoyingEncrypt;
1.打开xiaoyingEncrypt.db
2.输入密码
3.创建一个新的加密的数据库附加到原数据库上
4.导出数据到新的数据库
5.卸载新的数据库
其他:
还有修改密码之类的可以自行了解了解,都很简单。
开始加密:
查询说是在数据库open之后设置一个密码就行,实测就是扯淡。
我们本来是一个没有加密的数据库,所以直接setKey是没有用的。只能通过升级数据库来加密。
小影本身本地有数据库,所以需要对本地的空的数据库先加密,然后对于卸载了新安装的用户,直接setKey 就哦了。
数据库升级:
对于原本就安装然后升级上来的用户,因为本地本身存在未加密的数据库,所以需要去重新通过SQLCipher去新建替换掉旧的未加密的数据库。
所以在setKey之后还需要:判断数据库是否需要升级,当使用sqlchipher打开用sqlite生成的源数据库时,[self goodConnection]是为NO,即使openWithFlags或者open操作是YES。if(![self goodConnection]) {
// 无效链接
[self upgradeDatabase:self.databasePath];
}
如果goodConnection 返回NO,则说明需要数据迁移,基本的思路就是:
1.修改之前的未加密数据库名字
2.打开旧的数据库
3.创建一个新的db附加到原数据库上
4.导出数据到新的数据库上
5.卸载新的数据库
6.删除旧的数据库
数据库的迁移代码
总的加密思路:
1.open db
2.setKey
3.check goodConnection,如果返回NO 就去数据迁移
4.DONE
数据库升级出错解决方案:
数据库升级无法读取数据解决方案!!!但是,小影这边在数据库升级迁移这边,有三个数据库,最后一个xiaoying.db 路径需要从另外一个数据库中取出一个workFolderName,实测在取这个name的时候前两次是必取不出来,第三次之后才能取到,暂时未找到为什么。所以在已经存在数据库的情况下,也就是用户是升级App的情况下不会去setKey。(暂时的解决方法)
数据库升级的时候,在goodConnection 返回NO的时候,也就是数据库升级的时候,需要先调用close方法,在调用open方法,我的理解是先把旧的数据库关闭再打开新的加密后的数据库,这样才能正常的读取加密后的数据。
我们之前打开数据库用的是mesaSQLite,但是加密了之后就算你输入密码也不能打开,原因不明...
所以找了一个能打开的 DB Browser for SQLite... 实测可以打开。
至此,小影的数据库加密已经完成。后续的就是测试加密后的数据库读取速度以及在数据库升级的时候文件操作的时候,也就是数据库迁移中间如果出了问题怎么去保护,后面再更新。😘