osipxd / encrypted-datastore

Extensions to store DataStore in EncryptedFile
MIT License
151 stars 11 forks source link

Getting Crash on App Launch #20

Open praveenathuru opened 7 months ago

praveenathuru commented 7 months ago
Caused by: java.security.KeyStoreException: the master key android-keystore://_androidx_security_master_key_ exists but is unusable
    at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readOrGenerateNewMasterKey(AndroidKeysetManager.java:276)
    at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:237)
    at androidx.security.crypto.EncryptedFile$Builder.build(EncryptedFile.java:172)
    at com.huru.datastore.di.DataStoreModule$getDataStore$1.invoke(DataStoreModule.kt:61)
    at com.huru.datastore.di.DataStoreModule$getDataStore$1.invoke(DataStoreModule.kt:55)
    at io.github.osipxd.security.crypto.EncryptedPreferenceDataStoreFactoryKt.createEncrypted(EncryptedPreferenceDataStoreFactory.kt:61)
    at io.github.osipxd.security.crypto.EncryptedPreferenceDataStoreFactoryKt.createEncrypted$default(EncryptedPreferenceDataStoreFactory.kt:48)
osipxd commented 7 months ago

@praveenathuru, thank you for the report. Is it full stacktrace? Are there more causes?

praveenathuru commented 7 months ago

Not sure just got this one today as I launched my app after 24 hours on Android 9. I'm maintaining 2 different Data Stores variants in the application one for User and one for App level configuration. This is how I'm maintaining data stores.

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AppDataStore

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class UserDataStore

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class UserDataStoreManager

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class AppDataStoreManager

@Module
@InstallIn(SingletonComponent::class)
object DataStoreModule {
    @Provides
    @Singleton
    @UserDataStore
    fun provideUserDataPreference(@ApplicationContext context: Context): DataStore<Preferences> {
        return context.getDataStore(fileName = "user_data.preferences_pb")
    }

    @Provides
    @Singleton
    @AppDataStore
    fun provideAppDataPreference(@ApplicationContext context: Context): DataStore<Preferences> {
        return context.getDataStore(fileName = "app_data.preferences_pb")
    }

    private fun Context.getDataStore(fileName: String): DataStore<Preferences> {
        return PreferenceDataStoreFactory.createEncrypted {
            EncryptedFile.Builder(
                dataStoreFile(fileName = fileName),
                this,
                MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
                EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
            ).build()
        }
    }

    @Provides
    @Singleton
    @UserDataStoreManager
    fun provideUserDataStoreManager(@UserDataStore dataStore: DataStore<Preferences>): DataStoreManager {
        return DataStoreManagerImpl(dataStore)
    }

    @Provides
    @Singleton
    @AppDataStoreManager
    fun provideAppDataStoreManager(@AppDataStore dataStore: DataStore<Preferences>): DataStoreManager {
        return DataStoreManagerImpl(dataStore)
    }
}
osipxd commented 7 months ago

There are many reasons why the library can't decrypt master key, but firstly I'd suggest updating tink (the cryptographic library used under the hood) to the latest version:

dependencies {
    implementation("com.google.crypto.tink:tink-android:1.12.0")
}

If it does not help, look at this issue: https://github.com/tink-crypto/tink/issues/535 (especially this comment and this one) Similar issue in Google's issuetracker: b/176215143

praveenathuru commented 3 months ago

@osipxd any luck with this crash? we are facing crashes heavily in the production because of this. Any workaround you suggest? Did you updated the tink under the hood in this library?

osipxd commented 3 months ago

@praveenathuru, yes, I've updated Tink to the latest version in v1.0.0. Do you have fresh stack traces with an updated version?

praveenathuru commented 3 months ago

@osipxd We are using 1.0.0-beta01 version since long, now planning to upgrade it to v1.0.0. Hope v1.1.1-beta03 is not required at this point of time.

osipxd commented 3 months ago

Hope v1.1.1-beta03 is not required at this point of time.

It is required only if you want to use datastore 1.1.0.

osipxd commented 1 month ago

@praveenathuru, have you had a chance to check if the problem persists on the new version?

itamarb-ramm commented 1 month ago

@osipxd I'm having the same crash but only on a galaxy a35 so far. Using version 1.1.1-beta03.

osipxd commented 1 month ago

@osipxd I'm having the same crash but only on a galaxy a35 so far. Using version 1.1.1-beta03.

Could you tell me what versions of Android are affected?

itamarb-ramm commented 1 month ago

Android 14. Seems to run fine on A53 also with Android 14.

itamarb-ramm commented 1 month ago

Sorry @osipxd. It seems I am having a different issue:

Caused by javax.crypto.AEADBadTagException:
       at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:632)
       at javax.crypto.Cipher.doFinal(Cipher.java:2132)
       at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decryptInternal(AndroidKeystoreAesGcm.java:110)
       at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.decrypt(AndroidKeystoreAesGcm.java:93)
       at com.google.crypto.tink.KeysetHandle.decrypt(KeysetHandle.java:937)
       at com.google.crypto.tink.KeysetHandle.readWithAssociatedData(KeysetHandle.java:822)
       at com.google.crypto.tink.KeysetHandle.read(KeysetHandle.java:803)
       at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readMasterkeyDecryptAndParseKeyset(AndroidKeysetManager.java:383)
       at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:303)
       at androidx.security.crypto.EncryptedFile$Builder.build(EncryptedFile.java:172)
       at io.github.osipxd.security.crypto.EncryptedDataStoreSingletonDelegate$getValue$1$1.invoke(EncryptedDataStoreDelegate.kt:128)
       at io.github.osipxd.security.crypto.EncryptedDataStoreSingletonDelegate$getValue$1$1.invoke(EncryptedDataStoreDelegate.kt:116)
       at io.github.osipxd.security.crypto.EncryptedDataStoreFactoryKt.createEncrypted(EncryptedDataStoreFactory.kt:78)
       at io.github.osipxd.security.crypto.EncryptedDataStoreSingletonDelegate.getValue(EncryptedDataStoreDelegate.kt:116)
       at io.github.osipxd.security.crypto.EncryptedDataStoreSingletonDelegate.getValue(EncryptedDataStoreDelegate.kt:89)
osipxd commented 3 weeks ago

@itamarb-ramm, could you ensure that encrypted files are excluded from backup? Here is a discussion of the bug similar to yours.