react-native-keychain icon indicating copy to clipboard operation
react-native-keychain copied to clipboard

javax.crypto.BadPaddingException when accessing saved password on Android

Open ryanb-jobber opened this issue 4 years ago • 11 comments

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?

ryanb-jobber avatar Sep 09 '20 18:09 ryanb-jobber

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.

RikSchefferOberon avatar Oct 06 '20 11:10 RikSchefferOberon

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"
   }
]

RikSchefferOberon avatar Oct 06 '20 12:10 RikSchefferOberon

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!

SpreadTriad avatar Oct 07 '20 09:10 SpreadTriad

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) 

ryanb-jobber avatar Oct 08 '20 19:10 ryanb-jobber

what data did you save to produce this locally? Or what steps did you take?

RikSchefferOberon avatar Oct 12 '20 09:10 RikSchefferOberon

anyone found a solution? Seeing it also

oferRounds avatar Nov 05 '20 10:11 oferRounds

@oblador could this issue be relevant? https://stackoverflow.com/questions/4580982/javax-crypto-badpaddingexception

oferRounds avatar Nov 05 '20 10:11 oferRounds

@ryanb-jobber did you find any solution to this?

oferRounds avatar Nov 07 '20 19:11 oferRounds

@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 avatar Jan 16 '21 10:01 denissb

@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 avatar Feb 07 '23 03:02 timoteialbu

@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.

denissb avatar Feb 14 '23 20:02 denissb