oblador / react-native-keychain

:key: Keychain Access for React Native
MIT License
3.21k stars 520 forks source link

Reading from Keychain fails occasionally #321

Open defranke opened 4 years ago

defranke commented 4 years ago

I'm trying your example code from the readme on a Samsung Galaxy S6 Edge and sometimes reading the secret fails.

Writing to the keychain seems to work fine, but when I try to read from the keychain I sometimes get an error. In the android logs of the device I can see two exceptions while trying to read. The first exception is thrown before or right when the biometrics dialog is shown:

2020-03-27 14:09:54.244 17029-17383/com.rntest W/CipherStorageBase: User not authenticated
    android.security.keystore.UserNotAuthenticatedException: User not authenticated
        at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1153)
        at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1189)
        at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
        at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
        at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2977)
        at javax.crypto.Cipher.tryCombinations(Cipher.java:2884)
        at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2789)
        at javax.crypto.Cipher.chooseProvider(Cipher.java:956)
        at javax.crypto.Cipher.init(Cipher.java:1199)
        at javax.crypto.Cipher.init(Cipher.java:1143)
        at com.oblador.keychain.cipherStorage.CipherStorageBase$Defaults.lambda$static$1(CipherStorageBase.java:502)
        at com.oblador.keychain.cipherStorage.-$$Lambda$CipherStorageBase$Defaults$gUPKtklt7huSpCITAtk3nzsSgTY.initialize(lambda)
        at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:360)
        at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:315)
        at com.oblador.keychain.cipherStorage.CipherStorageKeystoreRsaEcb.decrypt(CipherStorageKeystoreRsaEcb.java:126)
        at com.oblador.keychain.KeychainModule.decryptToResult(KeychainModule.java:577)
        at com.oblador.keychain.KeychainModule.decryptCredentials(KeychainModule.java:545)
        at com.oblador.keychain.KeychainModule.getGenericPassword(KeychainModule.java:282)
        at com.oblador.keychain.KeychainModule.getGenericPasswordForOptions(KeychainModule.java:312)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:371)
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:150)
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:26)
        at android.os.Looper.loop(Looper.java:154)
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:225)
        at java.lang.Thread.run(Thread.java:762)

The second exception is thrown after I used my fingerprint to authenticate:

2020-03-27 14:03:55.363 17029-18371/com.rntest W/CipherStorageBase: Keystore operation failed
    java.security.InvalidKeyException: Keystore operation failed
        at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1168)
        at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1189)
        at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
        at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
        at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2977)
        at javax.crypto.Cipher.tryCombinations(Cipher.java:2884)
        at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2789)
        at javax.crypto.Cipher.chooseProvider(Cipher.java:956)
        at javax.crypto.Cipher.init(Cipher.java:1199)
        at javax.crypto.Cipher.init(Cipher.java:1143)
        at com.oblador.keychain.cipherStorage.CipherStorageBase$Defaults.lambda$static$1(CipherStorageBase.java:502)
        at com.oblador.keychain.cipherStorage.-$$Lambda$CipherStorageBase$Defaults$gUPKtklt7huSpCITAtk3nzsSgTY.initialize(lambda)
        at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:360)
        at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:315)
        at com.oblador.keychain.KeychainModule$InteractiveBiometric.onAuthenticationSucceeded(KeychainModule.java:806)
        at androidx.biometric.FingerprintHelperFragment$1$3.run(FingerprintHelperFragment.java:198)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:762)
     Caused by: android.security.KeyStoreException: Signature/MAC verification failed
        at android.security.KeyStore.getKeyStoreException(KeyStore.java:1107)
        at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1189) 
        at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54) 
        at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89) 
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265) 
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109) 
        at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2977) 
        at javax.crypto.Cipher.tryCombinations(Cipher.java:2884) 
        at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2789) 
        at javax.crypto.Cipher.chooseProvider(Cipher.java:956) 
        at javax.crypto.Cipher.init(Cipher.java:1199) 
        at javax.crypto.Cipher.init(Cipher.java:1143) 
        at com.oblador.keychain.cipherStorage.CipherStorageBase$Defaults.lambda$static$1(CipherStorageBase.java:502) 
        at com.oblador.keychain.cipherStorage.-$$Lambda$CipherStorageBase$Defaults$gUPKtklt7huSpCITAtk3nzsSgTY.initialize(lambda) 
        at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:360) 
        at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:315) 
        at com.oblador.keychain.KeychainModule$InteractiveBiometric.onAuthenticationSucceeded(KeychainModule.java:806) 
        at androidx.biometric.FingerprintHelperFragment$1$3.run(FingerprintHelperFragment.java:198) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
        at java.lang.Thread.run(Thread.java:762) 
2020-03-27 14:03:55.364 17029-17383/com.rntest I/RNKeychainManager: unblocking thread.
2020-03-27 14:03:55.364 17029-17383/com.rntest E/RNKeychainManager: Wrapped error: Keystore operation failed
2020-03-27 14:03:55.378 3112-3112/? W/keystore: key found but type doesn't match: 4 vs 1

This happens maybe in average every second time.

vonovak commented 4 years ago

hello, some bugs are device specific and hard to fix for people who do not experience them. Since you can reproduce it easily, I suggest you debug this and contribute a fix yourself. If you cannot do that, please provide a minimal repro - see https://stackoverflow.com/help/mcve and then maybe someone, some day, will pick it up and fix it. Thank you.

sebk commented 4 years ago

Same problem here, with the same device. Test project: https://github.com/sebk/RNKeyChainTest It is exactly the example project of the react-native-keychain project. I'm still debugging and trying things, but without any progress.

Edit: For the UserNotAuthenticatedException I found an interesting article: https://medium.com/@flschweiger/authentication-sucks-bad-security-too-345ed20463d4