2

我正在尝试通过应用升级来加密存储在我的内容提供商中的数据。我为此点击了以下链接,
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.access$1800(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


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

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


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

4

1 回答 1

6

数据库最初未加密,我希望通过应用程序升级对其进行加密

这不会自动发生,并且它不能作为SQLiteOpenHelperonUpgrade()路径的一部分发生(在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(),您可以继续尝试打开数据库。

于 2016-01-21T13:03:25.280 回答