我们都知道,Android的数据库文件存储在/data/data/your_packagename/databases路径下面,只要获得root权限就可以进入该目录,并可以查看、编辑你的应用数据,如果你的数据库存储了一些不允许用户查看和操作的敏感信息,则必须要给数据库加密。
SQLCipher是基于SQLite的开源数据库,在SQLite的基础上增加了加密功能,集成已经极其很方便。
step1
Sqlcipher的官方Android集成文档已经很老旧,官方团队在其blog中提到可以arr包的方式集成,即如果你是使用Android studio开发,那么你只需要在gradle中加入这一句:
compile 'net.zetetic:android-database-sqlcipher:3.4.0@aar'
如果你仍然在使用eclipse开发,也很简单:
- 请淘汰你的Eclipse,投入Android Studio的怀抱。
step2
创建一个SQLiteOpenHelper,只不过我们应该继承的是net.sqlcipher.database.SQLiteDatabase,而不是Android原本的android.database.sqlite.SQLiteDatabase,然后记得在你的应用做任何数据库操作之前调用SQLiteDatabase.loadLibs(this)去加载SQLCipher所需要的SO库,这一步在郭霖老师的文章中有详细的例子,这里不再赘述。
step3
如果你是在新建一个App,那么看到step2就足够了,但是如果你像我一样,早期并未意识到要解密数据库,那就要一起来看看如何将一个已存在的未加密数据库加密,这个在很多相关博客中都未提到。
SQLCipher官方提供了一个sqlcipher_export()方法去将未加密的数据库转换成加密数据库,将加密数据库转换成未加密数据库,官方文档有详细说明。
如果你只关心在Android中如何实现,那么请看代码:
public static void encrypt(Context ctxt, String dbName,
String passphrase) throws IOException {
File originalFile = ctxt.getDatabasePath(dbName);
if (originalFile.exists()) {
File newFile =
File.createTempFile("sqlcipherutils", "tmp",
ctxt.getCacheDir());
SQLiteDatabase db =
SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(),
"", null,
SQLiteDatabase.OPEN_READWRITE);
db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';",
newFile.getAbsolutePath(), passphrase));
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
int version = db.getVersion();
db.close();
db =
SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
passphrase, null,
SQLiteDatabase.OPEN_READWRITE);
db.setVersion(version);
db.close();
originalFile.delete();
newFile.renameTo(originalFile);
}
}
已加密的数据库转换成未加密数据库类似,大家可以根据官方文档自己实现。