I'm using SQLCipher for Android and am trying to determine the correct way to test whether a user-provided password is valid.
My first inclination was to just try and open the database with the given password, using the SQLCipher implementation of SQLiteOpenHelper.getReadableDatabase(password)
, and then catch the SQLiteException
that pops out.
This does work, but the problem is that because the Android API actually wraps the underlying C calls, it does a lot of the work for you - specifically, when you open a database using the Android API, it opens the database, runs the native C-level sqlite3_key
method (with the provided password), then tries to set the locale on the database, whether or not the provided password was correct.
At this point, the Android library tries to set the locale, and the underlying database throws the "encrypted or not a database" SQLiteException
, which is caught and rethrown; but before it is, an unrelated error is written to the logs, essentially saying the locale cannot be set and the database is being closed (with an included stack trace). Because this is specifically written by the Android library, I cannot suppress it, leaving an ugly error in the logs that is actually unrelated to my original problem, which was simply that I passed in the wrong password.
Because the Android library does not expose the C-level calls, I can't just use the method described in the SQLCipher API documentation regarding Testing the Key, because I don't have access to directly open the database.
I lean towards using the SQLiteDatabaseHook
, but as best I can tell, that precludes my use of SQLiteOpenHelper
, which does not appear to provide a way to set up a hook.
Does anyone else know any better way to test whether an input passphrase properly decrypts a SQLCipher database through the SQLCipher Android API? I would completely expect to call a method and check for an exception being thrown - what I don't want is for the operation to try and perform extraneous processing (like set locale) on the database and write a completely insuppressible error to my logs.