SQLCipherUtils.getDatabaseState 中带有 Room Persistence Library 异常的 SQLCipher

SQLCipher with Room Persistence Library exception in SQLCipherUtils.getDatabaseState

我的 Android 应用程序中有一个 Room 数据库,在我的 AppClass 中,我有一些检查数据库加密状态的逻辑,以便处理可能需要在数据库。但是,每当我在加密数据库上调用 SQLCipherUtils.getDatabaseState 时,它都会抛出 SQLiteException。但有趣的是,从 getDatabaseState 返回的状态不是 null 并且工作得很好,并且围绕对 getDatabaseState 的调用的 try-catch 块没有捕获异常。因此,据我所知,异常不会影响其余逻辑。但是,每次在数据库加密后启动应用程序时,看到此错误都出现在 LogCat 中令人沮丧。所以我的问题是,这个错误实际上是否表明存在问题?如果是,我该如何修复它,如果不是,我该如何消除错误?

应用程序中的数据库逻辑class(第一行抛出异常):

    try {
        // Get database state
        SQLCipherUtils.State state = SQLCipherUtils.getDatabaseState(getApplicationContext(), DB_NAME);

        // Check whether database is encrypted
        if (state == SQLCipherUtils.State.UNENCRYPTED) {
            // If it's unencrypted, encrypt the database
            try {
                // Get database instance
                FinancesDatabase db = FinancesDatabase.getDatabase(getApplicationContext());

                // Close database
                db.close();

                // Encrypt database with encryption key
                SQLCipherUtils.encrypt(getApplicationContext(), DB_NAME, sharedPrefs.getEncryptKey());
                Timber.i("Successfully encrypted database!");

            } catch (IOException e) {
                Timber.e(e, "Failed to encrypt previously unencrypted database!");
            }
        } else if (state == SQLCipherUtils.State.ENCRYPTED)
            // Otherwise, good to go
            Timber.i("Database is encrypted.  No action necessary.");

        else if (state == SQLCipherUtils.State.DOES_NOT_EXIST)
            // No database found.  Normal if first launch
            Timber.w("No database found.");

    } catch(Exception e) {
        Timber.e(e, "Failed to get database encryption state!");
    }

异常:

E/Database: file is not a database: , while compiling: select count(*) from sqlite_master;
net.sqlcipher.database.SQLiteException: file is not a database: , while compiling: select count(*) from sqlite_master;
    at net.sqlcipher.database.SQLiteCompiledSql.native_compile(Native Method)
    at net.sqlcipher.database.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:91)
    at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:64)
    at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:89)
    at net.sqlcipher.database.SQLiteQuery.<init>(SQLiteQuery.java:48)
    at net.sqlcipher.database.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:60)
    at net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1867)
    at net.sqlcipher.database.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1785)
    at net.sqlcipher.database.SQLiteDatabase.keyDatabase(SQLiteDatabase.java:2486)
    at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(SQLiteDatabase.java:2415)
    at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1149)
    at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1116)
    at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1065)
    at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1019)
    at com.commonsware.cwac.saferoom.SQLCipherUtils.getDatabaseState(SQLCipherUtils.java:62)
    at com.commonsware.cwac.saferoom.SQLCipherUtils.getDatabaseState(SQLCipherUtils.java:46)
    at edu.usm.cs.csc414.pocketfinances.AppClass.onCreate(AppClass.java:118)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1125)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6056)
    at android.app.ActivityThread.-wrap1(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1764)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

SQLCipherUtils.getDatabaseState 库中的实现:

public static State getDatabaseState(Context ctxt, String dbName) {
    SQLiteDatabase.loadLibs(ctxt);

    return(getDatabaseState(ctxt.getDatabasePath(dbName)));
}



public static State getDatabaseState(File dbPath) {
    if (dbPath.exists()) {
      SQLiteDatabase db=null;

      try {
        db=
          SQLiteDatabase.openDatabase(dbPath.getAbsolutePath(), "",
            null, SQLiteDatabase.OPEN_READONLY);

        db.getVersion();

        return(State.UNENCRYPTED);
      }
      catch (Exception e) {
        return(State.ENCRYPTED);
      }
      finally {
        if (db != null) {
          db.close();
        }
      }
    }

    return(State.DOES_NOT_EXIST);
}

直接记录by SQLCipher for Android。任何时候使用无效密码都会被记录下来。 getDatabaseState() 尝试使用空字符串作为密码短语打开数据库,因为这是未加密数据库的 "passphrase"。

避免此日志消息的选项是:

  • 不要对 Android 或

  • 使用 SQLCipher
  • 不要使用 getDatabaseState(),还要确保用户永远不会提供无效的密码