美文网首页Android
Android 使用SQLCipher进行数据库加密

Android 使用SQLCipher进行数据库加密

作者: 小小的coder | 来源:发表于2020-01-04 10:55 被阅读0次

在Android中通常使用SQLCipher对数据库进行加密。

SQLCipher是一个开源的SQLite加密扩展,支持对db文件进行256位的AES加密。

SQLCipher 官网:

https://www.zetetic.net/sqlcipher/
目前使用的是greenDaoAndroid数据库包,这个包目前是支持SQLCipher加密功能的,而且使用起来相当简单。

首先,在 Android 上添加 SQLCipher 依赖,在 build.gradle 中的 dependencies 里添加

dependencies {
/* 数据库加密框架 */
implementation 'net.zetetic:android-database-sqlcipher:3.5.7@aar'
}
然后,需要在使用时设置一个密码就行了,使用起来没什么难度

// 初始化数据库信息
devOpenHelper = new MyOpenHelper(MyApp.getContext(), DATABASE_NAME, null);
//mDaoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
//数据库加密
mDaoMaster = new DaoMaster(devOpenHelper.getEncryptedWritableDb(DATABASE_SQLCIPHER_PASSWORD));
就这样,数据库加密就做完了。

但是,这仅仅是对新建数据库来说,如果你之前就有已经在使用中的数据库,那么如果你直接运行项目,就会直接报错,数据库打开失败

Caused by: net.sqlcipher.database.SQLiteException: file is encrypted or is not a database: , while compiling: select count(*) from sqlite_master;
这是因为你你之前的数据库没有进行加密,现在是直接使用已加密的方法去使用,这样肯定是不行的。

当然,解决起来也不难,你只需要对已有的数据库进行加密,然后在调用就行了。

对已有数据库进行加密的方法如下:

/**

  • 对已有未加密数据库进行加密处理
    */
    public class DataBaseEncrypt {
    private static volatile DataBaseEncrypt nInstance;
    private Boolean isOpen = true;

    public DataBaseEncrypt() {
    }

    public static DataBaseEncrypt getInstences() {
    if (nInstance == null) {
    synchronized (DataBaseEncrypt.class) {
    if (nInstance == null) {
    nInstance = new DataBaseEncrypt();
    }
    }
    }
    return nInstance;
    }

    /**

    • 如果已有未加密的数据库旧表 先加密已有未加密数据库

    • @param context

    • @param passphrase
      */
      public void encrypt(Context context, String dbName, String passphrase) {
      File file = context.getDatabasePath(dbName);
      if (file.exists() && isOpen) {
      try {
      //创建临时数据库文件
      File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir());
      //对没有加密的数据库进行加密操作
      SQLiteDatabase db = SQLiteDatabase.openDatabase(file.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();
           file.delete();
           //对加密后的数据库进行重新命名
           newFile.renameTo(file);
           isOpen = false;
       } catch (Exception e) {
           isOpen = false;
       }
      

      }
      }

}
然后,在调用时如果能够正常调用直接返回,如果不能说明数据库没有加密过,直接调用加密方法

/**
 * 如果对已有数据进行加密,需要先对原有数据库进行加密操作
 * @return
 */
public synchronized Database getWritableDatabase() {
    try {
        return devOpenHelper.getEncryptedWritableDb(DATABASE_SQLCIPHER_PASSWORD);
    } catch (Exception e) {
        e.printStackTrace();
        //尝试加密后再打开
        DataBaseEncrypt.getInstences().encrypt(MyApp.getContext(), DATABASE_NAME, DATABASE_SQLCIPHER_PASSWORD);
        return devOpenHelper.getEncryptedWritableDb(DATABASE_SQLCIPHER_PASSWORD);
    }
}

最后,替换一下方法

// 初始化数据库信息
devOpenHelper = new MyOpenHelper(MyApp.getContext(), DATABASE_NAME, null);
//mDaoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
//数据库加密
mDaoMaster = new DaoMaster(getWritableDatabase());
到此,对数据的加密工作基本完成,不管是直接加密还是对已有数据库进行加密都没有问题。
————————————————
原文链接:https://blog.csdn.net/u014571139/article/details/102499777

相关文章

网友评论

    本文标题:Android 使用SQLCipher进行数据库加密

    本文链接:https://www.haomeiwen.com/subject/rluxactx.html