Android sqlite数据库加密

Android sqlite数据库加密

需求背景

Android系统自带的SQlite是明文存储,不支持加密,这样如果一旦第三方拿到设备端的db文件,相当于暴露了一切,所在在这个背景前提下,不得不对数据库进行加密。

解决方案

项目中使用的是greendao数据库框架,而greendao是支持数据库加密的,采用的是开源的SQLCipher进行加密。

对sqlite数据库进行加密

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)

你可能感兴趣的:(android)