Friday, 26 November 2021

Android 12 - Room db encryption issue

Getting this error on Android 12 only when trying to access the Dao for the first time in the app. Works perfectly fine in Android versions below.

AppModule:

    @Provides
    @Singleton
    fun provideApplication(): MyApplication = app

    @Provides
    @Singleton
    fun providePMDatabase(app: MyApplication): MyAppDatabase {
        val editable = SpannableStringBuilder(generateSymmetricKey("mykey").toString())
        val factory = SafeHelperFactory.fromUser(editable)
        return Room
                .databaseBuilder(app, MyAppDatabase::class.java, BuildConfig.DATABASE_NAME)
                .openHelperFactory(factory)
                .fallbackToDestructiveMigration()
                .build()
    }

    @Provides
    @Singleton
    fun provideSettingsDao(database: MyAppDatabase): SettingsDao = database.settingsDao()


    private fun generateSymmetricKey(keyAlias: String): Key {

        val keyStore = KeyStore.getInstance("AndroidKeyStore")
        keyStore.load(null)
        if (!keyStore.containsAlias(keyAlias)) {
            val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
            val keyGenParameterSpec =
                    KeyGenParameterSpec.Builder(
                            keyAlias,
                            KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                       .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                            .build()
            keyGenerator.init(keyGenParameterSpec)
            return keyGenerator.generateKey()
        }
        return keyStore.getKey(keyAlias, null)
    }

Room dependencies

//Room
implementation "androidx.room:room-runtime:2.3.0"
implementation "androidx.room:room-rxjava2:2.3.0"
kapt "androidx.room:room-compiler:2.3.0"

Error says: file is not a database: , while compiling: select count(*) from sqlite_master; The detailed log is as below:

SQLiteCompiledSql.java in net.sqlcipher.database.SQLiteCompiledSql.native_compile()
SQLiteCompiledSql.java line 91 in net.sqlcipher.database.SQLiteCompiledSql.compile()
SQLiteCompiledSql.java line 64 in net.sqlcipher.database.SQLiteCompiledSql.<init>()
SQLiteProgram.java line 89 in net.sqlcipher.database.SQLiteProgram.<init>()
SQLiteQuery.java line 48 in net.sqlcipher.database.SQLiteQuery.<init>()
SQLiteDirectCursorDriver.java line 60 in net.sqlcipher.database.SQLiteDirectCursorDriver.query()
SQLiteDatabase.java line 2012 in net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory()
SQLiteDatabase.java line 1898 in net.sqlcipher.database.SQLiteDatabase.rawQuery()
SQLiteDatabase.java line 2647 in net.sqlcipher.database.SQLiteDatabase.keyDatabase()
SQLiteDatabase.java line 2577 in net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal()
SQLiteDatabase.java line 1243 in net.sqlcipher.database.SQLiteDatabase.openDatabase()
SQLiteDatabase.java line 1318 in net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase()
SQLiteOpenHelper.java line 166 in net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase()
Helper.java line 172 in com.commonsware.cwac.saferoom.Helper$OpenHelper.getWritableSupportDatabase()
Helper.java line 82 in com.commonsware.cwac.saferoom.Helper.getWritableDatabase()
RoomDatabase.java line 622 in androidx.room.RoomDatabase.inTransaction()
RoomDatabase.java line 399 in androidx.room.RoomDatabase.assertNotSuspendingTransaction()
SettingsDao_Impl.java line 246 in mypackage.data.source.local.daos.SettingsDao_Impl.getSettingValue()
RequestInterceptor.kt line 65 in mypackage.data.source.remote.RequestInterceptor.intercept()
RealInterceptorChain.kt line 109 in okhttp3.internal.http.RealInterceptorChain.proceed()

UPDATE 1:

Issue is definitely with the encryption using com.commonsware.cwac.saferoom (which is not maintained anymore, so can't blame the library)

I changed it to use

    implementation 'net.zetetic:android-database-sqlcipher:4.5.0@aar'
    implementation "androidx.sqlite:sqlite-ktx:2.1.0"

and the code to

val editable = SpannableStringBuilder(generateSymmetricKey("mykey").toString())
// val factory = SafeHelperFactory.fromUser(editable)
val passphrase: ByteArray = SQLiteDatabase.getBytes(editable.toString().toCharArray())
val factory = SupportFactory(passphrase, null, false)

Application runs the first time. After that I get the error again.

NOTE If I comment out setting the factory i.e. Room.openHelperFactory(factory), application works fine.



from Android 12 - Room db encryption issue

No comments:

Post a Comment