我的使用场景:app做离线功能,相关数据是定时从服务端下载得到pb文件,但是pb文件中含有公司的数据,且该项目是to B的一个工具类项目,因此需要对pb文件做加密处理。
使用SQLCipher加密未存在的数据库很简单,而且google一下会有很多文章介绍;但是加密本地的pb文件这样的文章很少,自己实际操作过程中也遇到了问题,记录一下。SQLCipher加密的思路是:将要加密的pb文件中的所有的表全部拷贝一份并且带有密码,但是拷贝完成后需要自己删除要加密的文件,这样即使将pb文件拷贝出来也是打不开的了。
SQLCipher的集成和使用
1、首先在app的build.gradle中引入依赖:
implementation 'net.zetetic:android-database-sqlcipher:3.5.7@aar'
2、在使用SQLCipher之前要SQLiteDatabase.loadLibs(this);否则会报异常:
No implementation found for void net.sqlcipher.database.SQLiteDatabase.dbopen(java.lang.String, int) (tried Java_net_sqlcipher_database_SQLiteDatabase_dbopen and Java_net_sqlcipher_database_SQLiteDatabase_dbopen__Ljava_lang_String_2I)
我是在application中做的。
3、加密数据库(进行数据表的拷贝操作)
/**
* 加密数据库
*
* @param encryptedName 加密后的文件
* @param decryptedName 要加密的文件
* @param key 密码
*/
public void encryptMap(String encryptedName, String decryptedName, String key) {
String filePath = Constants.FILE_PATH_OFFLINE_DB;
File file = new File(filePath + "/" + encryptedName);
// 新建加密后的数据库文件,并设置其密码key
SQLiteDatabase dataTarget = SQLiteDatabase.openOrCreateDatabase(file, key, null);
String path = filePath + "/" + decryptedName;
//执行sql语句,连接未加密的数据库,并将其取别名为sourceLib,因为未加密数据库没密码,所以密码为""
dataTarget.execSQL("attach '" + path + "' as sourceLib key '';");
/*String passwordString = "1234"; //只能对已加密的数据库修改密码,且无法直接修改为“”或null的密码
database.changePassword(passwordString.toCharArray());*/
// 执行sql语句,在加密后的数据库文件中新建表,并将未加密的数据库表拷贝到新的加密数据库中,原数据库有多张表,该操作重复多少次
dataTarget.execSQL("create table new_table as select * from sourceLib.table");
//断开同加密后的数据库的连接
dataTarget.execSQL("detach database 'sourceLib'");
dataTarget.close();
}
其中sql语句中"create table new_table as select * from sourceLib.table"的new_table是加密后的表名,table是要加密的pb文件中的表名。
加密操作完成后记得把本地的要加密的pb文件删除,否则别人还是能用之前的pb文件看到数据。
4、打开数据库
/**
* 打开数据库(如果为空则表示数据库不存在)
*
* @param dbName
* @return
*/
public SQLiteDatabase openDatabase(String dbName) {
String filePath = Constants.FILE_PATH_OFFLINE_DB;
File jhPath = new File(filePath + "/" + dbName);
//查看数据库文件是否存在
if (jhPath.exists()) {
//存在则直接返回打开的数据库
sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(jhPath, ''your key'', null);
return sqLiteDatabase;
} else {
return null;
}
}
注意SQLiteDatabase和之后操作用到的Cursor都需要引用import net.sqlcipher.database.SQLiteDatabase;
这样之后数据库相关的操作api还是和原来一样,只是此时的pb文件没法用工具打开查看了,更拿不到里面的数据了。
网友评论