whorlwind
whorlwind copied to clipboard
UnrecoverableKeyException in prepareKeyStore
On Android 9, and possibly other Android versions, if you do the following steps:
- whorlwind.write("Key", ByteString.encodeUtf8("This is the secret data.")
- Go and disable the screen lock.
- Re-enable the screen lock and enable fingerprints.
- whorlwind.read("Key")...
The onError
will get called back with an exception like the following:
java.lang.RuntimeException: java.security.UnrecoverableKeyException: Failed to obtain information about key
W: java.lang.RuntimeException: java.security.UnrecoverableKeyException: Failed to obtain information about key
W: at com.squareup.whorlwind.RealWhorlwind.prepareKeyStore(RealWhorlwind.java:151)
W: at com.squareup.whorlwind.RealWhorlwind$1.run(RealWhorlwind.java:104)
W: at io.reactivex.internal.operators.completable.CompletableFromAction.subscribeActual(CompletableFromAction.java:34)
W: at io.reactivex.Completable.subscribe(Completable.java:2171)
W: at io.reactivex.Completable.subscribe(Completable.java:2244)
W: at io.reactivex.rxkotlin.SubscribersKt.subscribeBy(subscribers.kt:86)
W: at com.rnp.whorltest.MainActivity$onCreate$1$2.invoke(MainActivity.kt:62)
W: at com.rnp.whorltest.MainActivity$onCreate$1$2.invoke(MainActivity.kt:20)
W: at io.reactivex.rxkotlin.SubscribersKt$sam$io_reactivex_functions_Consumer$0.accept(Unknown Source:2)
W: at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:77)
W: at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.tryOnError(ObservableCreate.java:85)
W: at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onError(ObservableCreate.java:73)
W: at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:43)
W: at io.reactivex.Observable.subscribe(Observable.java:12030)
W: at io.reactivex.Observable.subscribe(Observable.java:12016)
W: at io.reactivex.Observable.subscribe(Observable.java:11976)
W: at io.reactivex.rxkotlin.SubscribersKt.subscribeBy(subscribers.kt:38)
W: at io.reactivex.rxkotlin.SubscribersKt.subscribeBy$default(subscribers.kt:37)
W: at com.rnp.whorltest.MainActivity$onCreate$1.onClick(MainActivity.kt:37)
W: at android.view.View.performClick(View.java:6597)
W: at android.view.View.performClickInternal(View.java:6574)
W: at android.view.View.access$3100(View.java:778)
W: at android.view.View$PerformClick.run(View.java:25885)
W: at android.os.Handler.handleCallback(Handler.java:873)
W: at android.os.Handler.dispatchMessage(Handler.java:99)
W: at android.os.Looper.loop(Looper.java:193)
W: at android.app.ActivityThread.main(ActivityThread.java:6669)
W: at java.lang.reflect.Method.invoke(Native Method)
W: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
W: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
W: Caused by: java.security.UnrecoverableKeyException: Failed to obtain information about key
W: at android.security.keystore.AndroidKeyStoreProvider.getKeyCharacteristics(AndroidKeyStoreProvider.java:234)
W: at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(AndroidKeyStoreProvider.java:356)
W: at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:101)
W: at java.security.KeyStore.getKey(KeyStore.java:1062)
W: at com.squareup.whorlwind.RealWhorlwind.prepareKeyStore(RealWhorlwind.java:127)
W: ... 29 more
W: Caused by: android.security.KeyStoreException: Key blob corrupted
W: at android.security.KeyStore.getKeyStoreException(KeyStore.java:823)
W: at android.security.keystore.AndroidKeyStoreProvider.getKeyCharacteristics(AndroidKeyStoreProvider.java:236)
W: ... 33 more
This sort of exception should likely clear the keystore and surface the exception, otherwise once a device gets into this state, it'll never get out of it again. Or, is there another way the library is supposed to be used to 'reset' the keystore so that a user can encrypt something again later?