android sqlite解密,SQlite数据库的加密与解密

一 关于SQlite

Android系统自带的SQlite是明文存储,不支持加密

二 SQlite加密方式

内容加密

主要写入读取数据时候做加密与解密的动作

缺点:

表结构暴露

无法直接搜索

数据库文件加密

对整个数据库文件加密

三 采用开源的SQLCipher进行加密

SQLCipher使用256-bit AES加密,由于其基于免费版的SQLite,主要的加密接口和SQLite是相同的,但也增加了一些自己的接口

3.1 对Android原生的数据库进行加密

(1)导入SQLCipher加密库

compile "net.zetetic:android-database-sqlcipher:3.5.9@aar"

(2)替换原生的包

* android.database.Cursor 为 net.sqlcipher.Cursor

* android.database.sqlite.SQLiteDatabase 为 net.sqlcipher.database.SQLiteDatabase

* android.database.SQLiteOpenHelper 为 net.sqlcipher.database.SQLiteOpenHelper

(3)加载SQLCipher所需要的SO库

SQLiteDatabase.loadLibs(this);

(4)获取读写对象时候附带密码

SQLiteOpenHelper.getWritableDatabase("密码"):

SQLiteOpenHelper.getReadableDatabase("密码")

3.2 对第三方DbFlow数据库进行加密

(1)替换为DbFlow加密库

// sql-cipher database encryption (optional)

compile "com.github.Raizlabs.DBFlow:dbflow-sqlcipher:${dbflow_version}"

compile "net.zetetic:android-database-sqlcipher:${sqlcipher_version}@aar"

(2)更改初始化的方法

FlowManager.init(FlowConfig.builder(this)

.addDatabaseConfig(DatabaseConfig.builder(QiDatabase.class)

.openHelper(new DatabaseConfig.OpenHelperCreator() {

@Override

public OpenHelper createHelper(DatabaseDefinition databaseDefinition, DatabaseHelperListener helperListener) {

return new SQLCipherOpenHelper(databaseDefinition, helperListener) {

@Override

protected String getCipherSecret() {

return "密码";

}

};

}

})

.build())

.build());

3.3 对未加密数据库的转换为加密的数据库

在加载SQLCipher所需要的SO库后及SQLiteDatabase.loadLibs(this)后,调用以下加密方法

/**

* 对未加密的数据库文件做加密处理

*

* @param ctxt 上下文

* @param dbName 数据库的文件名

* @param passphrase 密码

* @throws IOException

*/

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);

}

}

3.4 对加密数据库的保存为未加密的数据库文件

/**

* 将加密数据库文件保存为非加密的数据库文件

*

* @param context 上下文

* @param dbName 数据库名

* @param password 密码

* @param decFile 待保存的目标文件

* @return

*/

public static boolean decrypt(Context context, String dbName, String password, File decFile) {

boolean flag = false;

//先清空目标文件

decFile.delete();

try {

File originalFile = context.getDatabasePath(dbName);

SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(originalFile, password, null);

if (database.isOpen()) {

database.rawExecSQL(String.format("ATTACH DATABASE '%s' as plaintext KEY '';", decFile.getAbsolutePath()));

database.rawExecSQL("SELECT sqlcipher_export('plaintext');");

database.rawExecSQL("DETACH DATABASE plaintext;");

android.database.sqlite.SQLiteDatabase sqlDB = android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(decFile, null);

if (sqlDB != null)

flag = true;

sqlDB.close();

database.close();

}

} catch (Exception e) {

e.printStackTrace();

}

return flag;

// databaseFile.delete();

}

你可能感兴趣的:(android,sqlite解密)