Repository navigation
fix: keep RSA key for PKCS1 migration on padding mismatch - #1107
Merged
Merged
Conversation
RSADecrypt deleted the RSA/AES keys on InvalidKeyException (and the AES key + legacy IV on ProviderException) before tryRecoverCurrentAESKey could run the PKCS1 migration, logging out users upgrading from SDK <= 3.12.x / 2.x. RSADecrypt now only throws CryptoException; recovery and cleanup stay in tryRecoverCurrentAESKey, so the MGF1 regeneration from #1048 is unchanged. Fixes auth0/react-native-auth0#1696 Co-Authored-By: Claude
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
pmathew92
approved these changes
Oct 26, 2026
This was referenced Oct 26, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Users who saved credentials with Auth0.Android 3.12.1 or older (incl. 2.x) are logged out on the first launch after updating to 3.21.1 / 3.21.2 (and 4.2.0).
Root cause. Those versions created a PKCS1-only RSA key. Since #1048, when
RSADecryptgetsInvalidKeyException(KeystoreINCOMPATIBLE_PADDING_MODE), it deletes the RSA and AES keys before throwing. Its only caller,tryRecoverCurrentAESKey, then runsattemptPKCS1Migration, which needs that RSA key. The key is already gone (No RSA key found for migration), so new keys are generated and the stored credentials are cleared.The
ProviderExceptionbranch has a smaller version of the same problem:deleteAESKeys()also removes the legacy IV. Credentials saved by SDK 2.x use the legacy format, so on devices that report the padding mismatch asProviderException, the AES key migrates but the credentials can't be decrypted afterwards.Fix (
CryptoUtil.RSADecryptonly):InvalidKeyException | InvalidAlgorithmParameterException: no longer deletes keys; still throwsCryptoException(neverIncompatibleDeviceException).ProviderException: no longer callsdeleteAESKeys(); still throwsCryptoException.Recovery stays in
tryRecoverCurrentAESKey: it tries the PKCS1 migration first, and if that fails it deletes both keys and a new key pair is generated.ProviderException, 2.x dataNo public API changes.
Testing
Unit tests (
CryptoUtilTest)shouldKeepKeysAndThrowCryptoExceptionOn{InvalidKeyException,InvalidAlgorithmParameterException}WhenTryingToRSADecryptandshouldWrapProviderExceptionFromCipherInitInRSADecryptAsCryptoExceptionto assert thatRSADecryptno longer deletes keys.RSADecryptbefore the migration, with a KeyStore mock where a deleted key is really gone. The existing migration tests stubRSADecrypt, which is why this wasn't caught:shouldMigratePKCS1KeyWhenRealRSADecryptThrowsInvalidKeyExceptionshouldMigratePKCS1KeyAndKeepLegacyIVWhenRealRSADecryptThrowsProviderExceptionshouldRegenerateKeysWithoutIncompatibleDeviceWhenMgf1DigestIsRejected(guards fix(storage): authorize MGF1 digest to prevent INCOMPATIBLE_DEVICE on…3.x #1048)shouldMigratePKCS1KeyWhenEncryptIsTheFirstOperationAfterUpgrade./gradlew testReleaseUnitTest lintRelease: all unit tests pass, lint 0 errors.Device (Pixel 10, Android 17). Each run is an in-place update (
adb install -r) of a sample app that usesSecureCredentialsManager, with a real login against a test tenant:[PKCS1Padding], legacykey_iv), update, launchRSA key rejected … (legacy PKCS1 key or MGF1 digest mismatch)→PKCS1 migration successful→AES key re-encrypted with OAEP and stored[OAEPPadding],key_ivkept; cold start: no migration, success[PKCS1Padding]), update, launchgetCredentials(), then log in againINCOMPATIBLE_MGF_DIGEST→Deleting corrupted keys→New AES key generatedCRYPTO_EXCEPTION, keys regenerated; second login +getCredentials()succeedRSA key rejected …→Migration failed due to key access error→Deleting corrupted keys→New AES key generatedCRYPTO_EXCEPTION(notINCOMPATIBLE_DEVICE); second login +getCredentials()succeedCryptoUtillogsCryptoUtilwarningsNo Credentials were previously set; new login,getCredentials()and cold start succeedCryptoUtilpatch applied tomain)[PKCS1Padding], legacykey_iv), update, launch[OAEPPadding],key_ivkept; cold start: no migration, successChecklist