react-native-keychain
react-native-keychain copied to clipboard
javax.crypto.BadPaddingException when accessing saved password on Android
I am seeing fairly frequent occurrences of this exception from my app in production (I've never reproduced it locally).
Some subset of Android users are getting javax.crypto.BadPaddingException
when calling await Keychain.getGenericPassword()
Error is occurring at:
File "node_modules/react-native-keychain/index.js" line 192 col 28 in p return RNKeychainManager.getGenericPasswordForOptions(options); 42 File "node_modules/react-native/Libraries/BatchedBridge/NativeModules.js" line 103 col 55 in [anonymous] const enqueueingFrameError: ExtendedError = new Error();
I am saving the value using this code:
await Keychain.setGenericPassword(key, value, {
service: key,
accessible: ACCESSIBLE.ALWAYS,
storage: STORAGE_TYPE.AES,
});
And retrieving it via
const credentials = await Keychain.getGenericPassword({
service: key,
});
I'm seeing this on a variety of devices with Android versions ranging from 6 to 10. Any idea of what might cause this or how to resolve it?
I'm seeing the same here (with react-native-keychain 6.1.1), happening also on Android 11, all different kind of device manufacture. Also both ARM 32bit and 64bit.
I also have a stacktrace:
{
"class":"com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc",
"file":"CipherStorageKeystoreAesCbc.java",
"lineNumber":148,
"methodName":"decrypt"
},
{
"class":"com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc",
"file":"CipherStorageKeystoreAesCbc.java",
"lineNumber":160,
"methodName":"decrypt"
},
{
"class":"com.oblador.keychain.KeychainModule",
"file":"KeychainModule.java",
"lineNumber":623,
"methodName":"decryptToResult"
},
{
"class":"com.oblador.keychain.KeychainModule",
"file":"KeychainModule.java",
"lineNumber":590,
"methodName":[
"Filtered"
]
},
{
"class":"com.oblador.keychain.KeychainModule",
"file":"KeychainModule.java",
"lineNumber":295,
"methodName":[
"Filtered"
]
},
{
"class":"com.oblador.keychain.KeychainModule",
"file":"KeychainModule.java",
"lineNumber":323,
"methodName":[
"Filtered"
]
},
{
"class":"java.lang.reflect.Method",
"file":"Method.java",
"lineNumber":-2,
"methodName":"invoke"
},
{
"class":"com.facebook.react.bridge.JavaMethodWrapper",
"file":"JavaMethodWrapper.java",
"lineNumber":371,
"methodName":"invoke"
},
{
"class":"com.facebook.react.bridge.JavaModuleWrapper",
"file":"JavaModuleWrapper.java",
"lineNumber":150,
"methodName":"invoke"
},
{
"class":"com.facebook.react.bridge.queue.NativeRunnable",
"file":"NativeRunnable.java",
"lineNumber":-2,
"methodName":"run"
},
{
"class":"android.os.Handler",
"file":"Handler.java",
"lineNumber":873,
"methodName":"handleCallback"
},
{
"class":"android.os.Handler",
"file":"Handler.java",
"lineNumber":99,
"methodName":"dispatchMessage"
},
{
"class":"com.facebook.react.bridge.queue.MessageQueueThreadHandler",
"file":"MessageQueueThreadHandler.java",
"lineNumber":26,
"methodName":"dispatchMessage"
},
{
"class":"android.os.Looper",
"file":"Looper.java",
"lineNumber":216,
"methodName":"loop"
},
{
"class":com.facebook.react.bridge.queue.MessageQueueThreadImpl$4,
"file":"MessageQueueThreadImpl.java",
"lineNumber":225,
"methodName":"run"
},
{
"class":"java.lang.Thread",
"file":"Thread.java",
"lineNumber":764,
"methodName":"run"
}
]
A large percentage of our Android users is experiencing this issue. Some much needed version info:
We're using react-native-keychain 6.1.1, with react-native 0.61.5, and it seems like the issue was introduced after upgrading react-native-keychain from 6.0.0.
We're trying reproduce the issue locally. We've since updated to 6.2.0 and RN 0.63.2 and couldn't reproduce it (yet) against those versions, so it might be fixed by updating. Will update here if we find something.
@ryanb-jobber could you add the package version and react-native version that you are using and the stack trace to your report too? This will help us and the package devs to figure it out. Thx!
We are using react-native-keychain 6.0.0 with react-native 0.62.0
Here is a stack trace from an occurrence we reproduced locally
Stack trace
java.io.IOException: javax.crypto.BadPaddingException
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:133)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:249)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:225)
at com.oblador.keychain.cipherStorage.CipherStorageBase.copy(CipherStorageBase.java:487)
at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:364)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decryptBytes(CipherStorageKeystoreAesCbc.java:233)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decrypt(CipherStorageKeystoreAesCbc.java:141)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decrypt(CipherStorageKeystoreAesCbc.java:160)
at com.oblador.keychain.KeychainModule.decryptToResult(KeychainModule.java:614)
at com.oblador.keychain.KeychainModule.decryptCredentials(KeychainModule.java:581)
at com.oblador.keychain.KeychainModule.getGenericPassword(KeychainModule.java:293)
at com.oblador.keychain.KeychainModule.getGenericPasswordForOptions(KeychainModule.java:321)
at java.lang.reflect.Method.invoke(Native Method)
at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
at android.os.Looper.loop(Looper.java:214)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
at java.lang.Thread.run(Thread.java:919)
Caused by: javax.crypto.BadPaddingException
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:515)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:531)
at javax.crypto.Cipher.doFinal(Cipher.java:2002)
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:130)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:249)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:225)
at com.oblador.keychain.cipherStorage.CipherStorageBase.copy(CipherStorageBase.java:487)
at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:364)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decryptBytes(CipherStorageKeystoreAesCbc.java:233)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decrypt(CipherStorageKeystoreAesCbc.java:141)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decrypt(CipherStorageKeystoreAesCbc.java:160)
at com.oblador.keychain.KeychainModule.decryptToResult(KeychainModule.java:614)
at com.oblador.keychain.KeychainModule.decryptCredentials(KeychainModule.java:581)
at com.oblador.keychain.KeychainModule.getGenericPassword(KeychainModule.java:293)
at com.oblador.keychain.KeychainModule.getGenericPasswordForOptions(KeychainModule.java:321)
at java.lang.reflect.Method.invoke(Native Method)
at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
at android.os.Looper.loop(Looper.java:214)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
at java.lang.Thread.run(Thread.java:919)
Caused by: android.security.KeyStoreException: Invalid argument
at android.security.KeyStore.getKeyStoreException(KeyStore.java:1292)
at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:531)
at javax.crypto.Cipher.doFinal(Cipher.java:2002)
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:130)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:249)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:225)
at com.oblador.keychain.cipherStorage.CipherStorageBase.copy(CipherStorageBase.java:487)
at com.oblador.keychain.cipherStorage.CipherStorageBase.decryptBytes(CipherStorageBase.java:364)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decryptBytes(CipherStorageKeystoreAesCbc.java:233)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decrypt(CipherStorageKeystoreAesCbc.java:141)
at com.oblador.keychain.cipherStorage.CipherStorageKeystoreAesCbc.decrypt(CipherStorageKeystoreAesCbc.java:160)
at com.oblador.keychain.KeychainModule.decryptToResult(KeychainModule.java:614)
at com.oblador.keychain.KeychainModule.decryptCredentials(KeychainModule.java:581)
at com.oblador.keychain.KeychainModule.getGenericPassword(KeychainModule.java:293)
at com.oblador.keychain.KeychainModule.getGenericPasswordForOptions(KeychainModule.java:321)
at java.lang.reflect.Method.invoke(Native Method)
at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
at android.os.Looper.loop(Looper.java:214)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
at java.lang.Thread.run(Thread.java:919)
what data did you save to produce this locally? Or what steps did you take?
anyone found a solution? Seeing it also
@oblador could this issue be relevant? https://stackoverflow.com/questions/4580982/javax-crypto-badpaddingexception
@ryanb-jobber did you find any solution to this?
@ryanb-jobber - this exception can be caused by many things, but it typically happens on Android devices when the user changes his Biometric enrolment (adds/removes fingers) and tries to access a previously stored key, since that alters the KeyStore state on the device. You can try to reproduce it that way, hope it helps!
@denissb I've been trying pretty hard to replicate that scenario (adding/modifying the fingerprint biometrics), both on an emulator and a real device. I cannot seem to get that error at all though. It makes sense what you are saying, but I can't confirm it.
react-native-keychain: 6.0.0 react-native: 0.69.2
@timoteialbu
I was working with this library quite a while ago, but I believe it was caused by using STORAGE_TYPE.RSA
or STORAGE_TYPE.AES
. You can try to reproduce while using one of those.