是否有正确的方法来测试用户提供的SQLCipher密码在Android上是否有效?

问题描述 投票:8回答:3

我正在使用SQLCipher for Android,正在尝试确定测试用户提供的密码是否有效的正确方法。

我的第一个倾向是尝试使用给定的密码,使用SQLiteOpenHelper.getReadableDatabase(password)的SQLCipher实现打开数据库,然后捕获弹出的SQLiteException

这确实有效,但是问题在于,因为Android API实际上包装了基础C调用,所以它为您完成了很多工作-特别是,当您使用Android API打开数据库时,它将打开数据库并运行本机C级sqlite3_key方法(使用提供的密码),然后尝试在数据库上设置语言环境,无论提供的密码是否正确。

[此时,Android库尝试设置区域设置,并且基础数据库抛出被捕获并重新抛出的“加密或非数据库” SQLiteException;但在此之前,一个不相关的错误被写入日志,这实际上是说无法设置语言环境并且正在关闭数据库(包括堆栈跟踪)。因为这是由Android库专门编写的,所以我无法抑制它,在日志中留下一个难看的错误,该错误实际上与我的原始问题无关,这仅仅是我输入了错误的密码。

由于Android库未公开C级调用,所以我不能仅使用SQLCipher API文档中有关Testing the Key的方法,因为我无权直接打开数据库。

[我倾向于使用SQLiteDatabaseHook,但是据我所知,这排除了我对SQLiteOpenHelper的使用,这似乎无法提供建立钩子的方法。

还有其他人知道更好的方法来测试输入密码短语是否通过SQLCipher Android API正确解密SQLCipher数据库吗?我完全希望调用一个方法并检查是否引发了异常-我不希望该操作尝试在数据库上执行无关的处理(如set locale),并向日志中写入完全无法抑制的错误。

android sqlcipher
3个回答
1
投票

用于Android的SQLCipher不知道您在sqlite3_key调用后提供的密码无效,因为在sqlite3_key之后针对数据库发出SQL命令之前,不会使用数据库密钥,例如[您在上面引用的setLocale(...)方法。问题是,提供无效密钥可能只是其他可能出现的情况之一,在执行第一个SQL语句时可能是问题所在。数据文件损坏,HMAC检查失败或打开非数据库文件都可能导致此错误消息。有关此内容的详细说明,请查看此thread。尝试打开数据库并在客户端应用程序中进行相应处理时,最好捕获异常。


1
投票

我没有更好的测试方法。我只想提供一些代码,所以当其他人查找时,他们可能会发现一些有用的代码片段。至少当我发现这个问题时,我很想看看一些代码如何进行检查:)

我在android中的操作方式是这样:

    // Simply get an instance of SQLiteOpenHelper.
    dbHelperObj = myDatabase.getInstance(this, str_username, version);

    // Now we try to open the database with the password from the user.
    try {
        dbObj = dbHelperObj.getReadableDatabase(str_password);

    // The only possible error now must be a wrong password.
    } catch (Exception e) {
        dbHelperObj.close();

        // Do stuff to tell the user he provided a wrong password.
    }

0
投票

当前,唯一验证密码短语的方法是对数据库进行操作,并检查其是否抛出net.sqlcipher.database.SQLiteException。因此,对于那些将SQLCipher与Room ORM一起使用的人,下面的代码应该可以完成工作。

使用提供的密码获取Room数据库实例后,调用isPassphraseValid()函数并将数据库实例传递给它。

    /* Passphrase validation: */
    private fun isPassphraseValid(db: MyRoomDatabase): Boolean {
        return try {
            db.openHelper.readableDatabase
            Log.d("sql-log", "Pass phrase is valid.")
            true
        } catch (e: net.sqlcipher.database.SQLiteException) {
            e.printStackTrace()
            Log.d("sql-log", "Pass phrase is not valid.")
            false
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.