Android系统自带的SQlite是明文存储,不支持加密,这样如果一旦第三方拿到设备端的db文件,相当于暴露了一切,所在在这个背景前提下,不得不对数据库进行加密。
项目中使用的是greendao数据库框架,而greendao是支持数据库加密的,采用的是开源的SQLCipher进行加密。
1.由于greendao中已经依赖了SQLCipher,所以app无需额外依赖
2.程序初始化的时候需要加载SQLCipher所需要的SO库
SQLiteDatabase.loadLibs(context);
3.对数据库加密
private void encrypt(String password, File fileDir) {
try {
File dbFile = new File(fileDir, DB_NAME);
File encryptDbFile = new File(fileDir, DB_NAME_ENCRYPT);
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(dbFile.getAbsolutePath(), "", null);
//SQLiteDatabase database = SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), "", null, SQLiteDatabase.OPEN_READWRITE);
//连接到加密后的数据库,并设置密码
database.rawExecSQL(String.format("ATTACH DATABASE '%s' as encrypted KEY '" + password + "';", encryptDbFile.getAbsolutePath()));
//输出要加密的数据库表和数据到加密后的数据库文件中
database.rawExecSQL("SELECT sqlcipher_export('encrypted');");
//断开同加密后的数据库的连接
database.rawExecSQL("DETACH DATABASE encrypted;");
SQLiteDatabase decrypteddatabase = SQLiteDatabase.openDatabase(encryptDbFile.getAbsolutePath(), password, null, SQLiteDatabase.OPEN_READWRITE);
decrypteddatabase.setVersion(database.getVersion());
decrypteddatabase.close();
database.close();
LogPrint.i("DbCore", "end encrypt");
} catch (Exception e) {
LogPrint.i("DbCore", e.getMessage());
e.printStackTrace();
}
4.对数据库解密
public void decrypt(String password, File fileDir) {
LogPrint.i("DbCore", "start decrypt");
try {
File dbFile = new File(fileDir, DB_NAME);
File encryptDbFile = new File(fileDir, DB_NAME_ENCRYPT);
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(encryptDbFile.getAbsolutePath(), password, null);
//SQLiteDatabase database = SQLiteDatabase.openDatabase(encryptDbFile.getAbsolutePath(), password, null, SQLiteDatabase.OPEN_READWRITE);
//连接到加密后的数据库,并设置密码
database.rawExecSQL(String.format("ATTACH DATABASE '%s' as encrypted KEY '';", dbFile.getAbsolutePath()));
//输出要加密的数据库表和数据到加密后的数据库文件中
database.rawExecSQL("SELECT sqlcipher_export('encrypted');");
//断开同加密后的数据库的连接
database.rawExecSQL("DETACH DATABASE encrypted;");
SQLiteDatabase decrypteddatabase = SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), "", null, SQLiteDatabase.OPEN_READWRITE);
decrypteddatabase.setVersion(database.getVersion());
decrypteddatabase.close();
database.close();
LogPrint.i("DbCore", "end decrypt");
} catch (Exception e) {
LogPrint.i("DbCore", e.getMessage());
e.printStackTrace();
}
}
5.获取带密码的读写数据库对象
helper.getEncryptedWritableDb(DB_PASSWORD)