【问题标题】:SQLCipher with Room Persistence Library exception in SQLCipherUtils.getDatabaseStateSQLCipherUtils.getDatabaseState 中带有 Room Persistence Library 异常的 SQLCipher
【发布时间】:2018-11-23 20:39:00
【问题描述】:

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

Application 类中的数据库逻辑(第一行抛出异常):

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

【问题讨论】:

    标签: android sqlcipher commonsware-cwac


    【解决方案1】:

    这是直接记录by SQLCipher for Android。每次使用无效密码时都会记录下来。 getDatabaseState() 尝试使用空字符串作为密码打开数据库,因为这是未加密数据库的“密码”。

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

    • 不要将 SQLCipher 用于 Android,或者

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

    【讨论】:

    • 对不起,先生,我不明白你的意思。我需要使用getDatabaseState() 来检查退出数据库的数据是否加密?请帮助我。我也陷入了同样的问题。谢谢
    • @RavindraKushwaha:如果您的症状与原始问题的人相同,那么您没有问题。这是 SQLCipher for Android 记录的堆栈跟踪。您的应用程序没有崩溃。这是预期的正常行为。
    • 谢谢先生 :) 什么问题,我现在知道了 :- 1)。我加密了现有的数据库,它加密成功.. 2)。当我在均匀的时间(每秒)重新运行应用程序时,我的应用程序会崩溃并且不会产生任何日志..
    猜你喜欢
    • 2017-11-09
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 2018-04-05
    • 2017-10-18
    • 1970-01-01
    相关资源
    最近更新 更多