Skip to content

Commit 715bcc8

Browse files
committed
handling co pilot review comments
1 parent 967376e commit 715bcc8

File tree

1 file changed

+49
-15
lines changed
  • auth0/src/main/java/com/auth0/android/authentication/storage

1 file changed

+49
-15
lines changed

auth0/src/main/java/com/auth0/android/authentication/storage/CryptoUtil.java

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,17 @@ class CryptoUtil {
5656
private static final String RSA_TRANSFORMATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
5757
/**
5858
* !!! WARNING !!!
59-
* "RSA/ECB/PKCS1Padding" is deprecated due to vulnerabilities (see Bleichenbacher attacks, etc),
60-
* and should only be used here for *legacy key migration only*. All new data must use OAEP padding.
61-
* REMOVE SUPPORT FOR THIS AS SOON AS ALL DATA IS MIGRATED.
59+
* "RSA/ECB/PKCS1Padding" is cryptographically deprecated due to vulnerabilities
60+
* (e.g. Bleichenbacher padding oracle attacks) and MUST NOT be used for encrypting
61+
* new data or for any general-purpose RSA operations.
62+
*
63+
* This transformation exists solely to DECRYPT pre-existing legacy data that was
64+
* originally encrypted with PKCS#1 v1.5 padding, so that it can be re-encrypted
65+
* using the secure OAEP-based {@link #RSA_TRANSFORMATION}. Once all legacy data has
66+
* been migrated, support for this constant and any code paths that use it should be
67+
* removed.
6268
*/
63-
private static final String OLD_PKCS1_RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
69+
private static final String LEGACY_PKCS1_RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
6470
// https://developer.android.com/reference/javax/crypto/Cipher.html
6571
@SuppressWarnings("SpellCheckingInspection")
6672
private static final String AES_TRANSFORMATION = "AES/GCM/NOPADDING";
@@ -98,6 +104,31 @@ public CryptoUtil(@NonNull Context context, @NonNull Storage storage, @NonNull S
98104
this.storage = storage;
99105
}
100106

107+
/**
108+
* Decrypts data that was encrypted using legacy RSA/PKCS1 padding.
109+
* <p>
110+
* WARNING: This must only be used for decrypting legacy data during migration.
111+
* New code must always use OAEP padding for RSA encryption/decryption.
112+
*
113+
* @param encryptedData The data encrypted with PKCS1 padding
114+
* @param privateKey The private key for decryption
115+
* @return The decrypted data
116+
* @throws NoSuchPaddingException If PKCS1 padding is not available
117+
* @throws NoSuchAlgorithmException If RSA algorithm is not available
118+
* @throws InvalidKeyException If the private key is invalid
119+
* @throws BadPaddingException If the encrypted data has invalid padding
120+
* @throws IllegalBlockSizeException If the encrypted data size is invalid
121+
*/
122+
@NonNull
123+
private static byte[] RSADecryptLegacyPKCS1(@NonNull byte[] encryptedData,
124+
@NonNull PrivateKey privateKey)
125+
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
126+
BadPaddingException, IllegalBlockSizeException {
127+
Cipher rsaPkcs1Cipher = Cipher.getInstance(LEGACY_PKCS1_RSA_TRANSFORMATION);
128+
rsaPkcs1Cipher.init(Cipher.DECRYPT_MODE, privateKey);
129+
return rsaPkcs1Cipher.doFinal(encryptedData);
130+
}
131+
101132
/**
102133
* Attempts to recover the existing RSA Private Key entry or generates a new one as secure as
103134
* this device and Android version allows it if none is found.
@@ -410,11 +441,12 @@ byte[] getAESKey() throws IncompatibleDeviceException, CryptoException {
410441
}
411442

412443
if (rsaKey != null && keyAliasUsed != null) {
413-
// WARNING: Using PKCS1 padding here is intentional and ONLY for decrypting legacy data
414-
// Do NOT use PKCS1 padding for encryption in new code; always use OAEP padding instead.
415-
Cipher rsaPkcs1Cipher = Cipher.getInstance(OLD_PKCS1_RSA_TRANSFORMATION);
416-
rsaPkcs1Cipher.init(Cipher.DECRYPT_MODE, rsaKey.getPrivateKey());
417-
byte[] decryptedAESKey = rsaPkcs1Cipher.doFinal(encryptedAESBytes);
444+
// WARNING: Using PKCS1 padding here is intentional and ONLY for decrypting legacy data.
445+
// This cipher must NEVER be used for encryption or for any new data; always use OAEP instead.
446+
byte[] decryptedAESKey = RSADecryptLegacyPKCS1(
447+
encryptedAESBytes,
448+
rsaKey.getPrivateKey()
449+
);
418450
deleteRSAKeys();
419451

420452
// Re-encrypt AES key with NEW OAEP RSA key (4096-bit)
@@ -435,8 +467,9 @@ byte[] getAESKey() throws IncompatibleDeviceException, CryptoException {
435467
deleteRSAKeys();
436468
deleteAESKeys();
437469
}
470+
} else {
471+
throw e;
438472
}
439-
throw e;
440473
} catch (CryptoException e) {
441474
// RSA decryption failed - the encrypted AES key is corrupted or the RSA key is invalid
442475
// Delete keys and regenerate them
@@ -450,11 +483,12 @@ byte[] getAESKey() throws IncompatibleDeviceException, CryptoException {
450483
try {
451484
byte[] encryptedOldAESBytes = Base64.decode(encodedOldAES, Base64.DEFAULT);
452485
KeyStore.PrivateKeyEntry rsaKeyEntry = getRSAKeyEntry();
453-
// WARNING: Using PKCS1 padding here is intentional and ONLY for decrypting legacy data
454-
// Do NOT use PKCS1 padding for encryption in new code; always use OAEP padding instead.
455-
Cipher rsaPkcs1Cipher = Cipher.getInstance(OLD_PKCS1_RSA_TRANSFORMATION);
456-
rsaPkcs1Cipher.init(Cipher.DECRYPT_MODE, rsaKeyEntry.getPrivateKey());
457-
byte[] decryptedAESKey = rsaPkcs1Cipher.doFinal(encryptedOldAESBytes);
486+
// WARNING: Using PKCS1 padding here is intentional and ONLY for decrypting legacy data.
487+
// This cipher must NEVER be used for encryption or for any new data; always use OAEP padding instead.
488+
byte[] decryptedAESKey = RSADecryptLegacyPKCS1(
489+
encryptedOldAESBytes,
490+
rsaKeyEntry.getPrivateKey()
491+
);
458492

459493
byte[] encryptedAESWithOAEP = RSAEncrypt(decryptedAESKey);
460494
String newEncodedEncryptedAES = new String(Base64.encode(encryptedAESWithOAEP, Base64.DEFAULT), StandardCharsets.UTF_8);

0 commit comments

Comments
 (0)