我正在使用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)并在我的日志中写入一个完全不可抑制的错误。
答案 0 :(得分:0)
Android的SQLCipher在sqlite3_key
调用后不知道您提供的密码无效,因为在sqlite3_key
之后对数据库发出SQL命令之前,不会使用数据库密钥,例如您在上面引用的setLocale(...)
方法。问题是,提供无效密钥可能只是在第一个SQL语句执行时可能出现问题的其他可能情况之一。损坏的数据文件,失败的HMAC检查或打开非数据库文件可能会导致此相同的错误消息。有关详细说明,请查看此thread。在尝试打开数据库并在客户端应用程序中相应地处理时,最好捕获异常。
答案 1 :(得分:0)
我没有更好的测试方法。我只是想提供一些代码,所以当其他人查看时,他们可能会找到一些有用的代码片段。 至少当我发现这个问题时,我会很高兴看到一些代码如何进行检查:)
我在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.
}
答案 2 :(得分: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
}
}