EncryptedSharedPreferences result in UnrecoverableKeyException

Viewed 2452

I'm using the new EncryptedSharedPreferences class in a way recommended from Google:

private fun securePrefs(context: Context): SharedPreferences {
    val fileName = "sharedPrefsSecure"
    val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
    return EncryptedSharedPreferences.create(fileName, masterKeyAlias, context,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM)
}

However, the app crashed on emulator (Pixel 2 API 26) on the next day. This happens every time I start the app, until I fully uninstall it and reinstall again (from Studio with Run) - then it works fine. However, once I restart the emulator, it starts to crash again until full reinstall. My Samsung was fine, even after restart. I wonder if I will also get something similar on real devices.

Here is the crash stack trace:

2020-02-24 17:42:52.632 12398-12398/com.myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myapp, PID: 12398
    java.security.UnrecoverableKeyException: Failed to obtain information about key
        at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreSecretKeyFromKeystore(AndroidKeyStoreProvider.java:282)
        at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:98)
        at java.security.KeyStore.getKey(KeyStore.java:1062)
        at com.google.crypto.tink.integration.android.AndroidKeystoreAesGcm.<init>(AndroidKeystoreAesGcm.java:48)
        at com.google.crypto.tink.integration.android.AndroidKeystoreKmsClient.getAead(AndroidKeystoreKmsClient.java:111)
        at com.google.crypto.tink.integration.android.AndroidKeystoreKmsClient.getOrGenerateNewAeadKey(AndroidKeystoreKmsClient.java:130)
        at com.google.crypto.tink.integration.android.AndroidKeysetManager.<init>(AndroidKeysetManager.java:118)
        at com.google.crypto.tink.integration.android.AndroidKeysetManager.<init>(AndroidKeysetManager.java:88)
        at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build(AndroidKeysetManager.java:185)
        at androidx.security.crypto.EncryptedSharedPreferences.create(EncryptedSharedPreferences.java:123)
        at com.myapp.base.service.DefaultKeystoreService.securePrefs(DefaultKeystoreService.kt:43)
        at com.myapp.base.service.DefaultKeystoreService.sharedPrefsForKey(DefaultKeystoreService.kt:37)
        at com.myapp.base.service.DefaultKeystoreService.get(DefaultKeystoreService.kt:17)
        at com.myapp.base.repository.DefaultCredentialsRepository.getRefreshToken(DefaultCredentialsRepository.kt:78)
        at com.myapp.base.repository.DefaultCredentialsRepository.getCredentials(DefaultCredentialsRepository.kt:20)
        at com.myapp.base.repository.DefaultCredentialsRepository.runAuthFlowWithTokens(DefaultCredentialsRepository.kt:28)
        at com.myapp.main.AppRootModel$startAuthFlow$1.invokeSuspend(AppRootModel.kt:43)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:313)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
        at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)
        at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:54)
        at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
        at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
        at com.myapp.main.AppRootModel.startAuthFlow(AppRootModel.kt:39)
        at com.myapp.main.AppRootModel.<init>(AppRootModel.kt:33)
        at java.lang.Class.newInstance(Native Method)
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
        at com.myapp.main.AppRootFragment.getViewModel(Unknown Source:7)
        at com.myapp.main.AppRootFragment.onCreateView(AppRootFragment.kt:25)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
        at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
2020-02-24 17:42:52.633 12398-12398/com.myapp E/AndroidRuntime:     at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2629)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2722)
        at androidx.fragment.app.FragmentStateManager.activityCreated(FragmentStateManager.java:346)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1188)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:247)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1333)
        at android.app.Activity.performStart(Activity.java:6992)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2780)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
     Caused by: android.security.KeyStoreException: Invalid key blob
        at android.security.KeyStore.getKeyStoreException(KeyStore.java:695)
        at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreSecretKeyFromKeystore(AndroidKeyStoreProvider.java:283)
            ... 69 more
1 Answers

If you are facing the issue in Emulator , I suggest uninstall and install the app again. It works well in real device, this issue generally happening in Emulator. It worked for me in real device and failed in emulator. Then I uninstalled and installed again it worked.

Related