使用 SQLCipher -Android 将纯内容提供程序数据(由 SQLite 支持)升级为加密

Upgrading plain content provider data(backed by SQLite) to encrypted using SQLCipher -Android

我正在尝试通过应用程序升级来加密存储在我的内容提供商中的数据。为此,我遵循了下面的 link,
How to implement SQLCipher when using SQLiteOpenHelper

虽然如果完成新安装这一切都很好,但如果我进行升级,应用程序会崩溃并出现以下错误

    net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at  android.app.ActivityThread.handleReceiver(ActivityThread.java:3009)
at  android.app.ActivityThread.access00(ActivityThread.java:177)
at  android.app.ActivityThread$H.handleMessage(ActivityThread.java:1526)
at  android.os.Handler.dispatchMessage(Handler.java:102)
at  android.os.Looper.loop(Looper.java:145)
at  android.app.ActivityThread.main(ActivityThread.java:5951)
at  java.lang.reflect.Method.invoke(Native Method)
at  java.lang.reflect.Method.invoke(Method.java:372)
at  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
at  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
    Caused by: net.sqlcipher.database.SQLiteException: file is encrypted or is not a database


我什至尝试删除现有的 table 并创建一个新的 table 只是为了看看这是否解决了问题,但没有,这也没有任何帮助。请建议如何解决这个问题,我的助手 class 如下所示,

                public class MyDBHelper extends SQLiteOpenHelper {
                public MyDBHelper(Context context) {
                    super(context, DATABASE_NAME, null, DATABASE_VERSION);
                    SQLiteDatabase.loadLibs(context);
                }
                public static final String DATABASE_NAME = "mydb.db";

                private static final int DATABASE_VERSION = 2; // before attempting encryption it was 1

                @Override
                public void onCreate(SQLiteDatabase db) {
                    createTables(db);
                }

                @Override
                public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                    db.execSQL("DROP TABLE IF EXISTS " + "TEST_TABLE");
                    createTables(db);
                }

                private void createTables(SQLiteDatabase db){
                    db.execSQL(MyDBQueries.CREATE_TEST_TABLE);
                }
            }


我更新后的提供商现在只需使用一个密钥即可打开数据库,如下所示,

                SQLiteDatabase db = databaseHelper.getWritableDatabase("encryptionKey");


正如我提到的,全新安装效果很好,但升级会使应用程序崩溃。请建议如何解决此问题。

Database is not encrypted initially, I want that to be encrypted with app upgrade

这不会自动发生,也不会作为 SQLiteOpenHelper 及其 onUpgrade() 路径的一部分发生(在调用 onUpgrade() 时,SQLiteOpenHelper 将已经尝试打开未加密的数据库,这将失败,但您显示的异常除外)。

您需要单独加密该数据库。这段代码是我用过的:

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

encrypt()returns之后,您可以继续尝试打开数据库。