Since Room does not provide official support for encryption I decided to ask here.
I am trying to update database password of already encrypted database. I manage to do it with suggested PRAGMA rekey="newKey"
, meaning when I pull the database files from the device and use SQLCipher for Windows, I can read it with newKey
. Problem happens when I inject the Room database in my repository, that instance probably tries to read the database with old password and I get the file is not a database
exception.
It seems to me like underlying SQLite database is encrypted with new key, but Room is not aware of it and uses oldKey
which was set through SupportOpenHelperFactory
. So my current pseudo code which works is this:
fun buildDB(): RoomDB {
//set builder with old pass
val builder = Room.databaseBuilder(...).openHelperFactory(SupportOpenHelperFactory("oldKey".toByteArray())).
var db = builder.build()
// change db pass
db.openHelper.writableDatabase.query("PRAGMA rekey = 'newKey';")
// here I still have open connection with newKey so I could do any kind of queries and it works
// for example
// db.openHelper.writableDatabase.query("SELECT COUNT(*) FROM sqlite_schema;")
// close the connection
db.close()
// create new builder with new pass
val builder2 = Room.databaseBuilder(...).openHelperFactory(SupportOpenHelperFactory("newKey".toByteArray())).
db = builder2.build()
return db
}
then this db
instance is returned to my @Provides
and @Singleton
annotated method in my Dagger module.
So my questions are
- Why does it work in the
buildDB
function but once that instance is injected into my repository for example, I can not query it? It is same instance but it seems like Room closed the connection and tried to open it with old password. - Is there a better way to achieve this, without the need to recreate RoomDatabase instance? Is there a way to update the password on already created instance?
- Why is there no
changePassword
function inSupportSQLiteDatabase
like it was inSQLiteDatabase
?