About a year ago, I wrote an application for Android and used a class in it RSA In this class, there was the following code snippet and the application worked
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
But when I re-entered the application code, I did not open the new encrypted information to change the private key until I changed the above code line to the following code line.
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
The problem is that if I replace the above code snippet in class RSA it is no longer possible to open previously encrypted information (with the same keys as before). And I see the following error
javax.crypto.BadPaddingException: error:04000084:RSA routines:OPENSSL_internal:PKCS_DECODING_ERROR
RSA decryption
public static byte[] decryptByPrivateKey(byte[] data, String key)
throws Exception {
byte[] keyBytes = decryptBASE64(key);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
RSA key pairs can be used within different RSA based schemes, such as PKCS#1 and OAEP padding for encryption, and PKCS#1 and PSS padding for signing. However, there is only one key pair generation possible, which is simply denoted "RSA"
.
If only "RSA"
is used as input string it will use the defaults set for the specific cryptography provider, which is - in this case - the first provider that implements RSA using keys in software. Apparently that's different on Android from PKCS#1 padding (assuming that you still use the original list of providers, of course). One stupid thing in Java is that you cannot programmatically find out which defaults are used; getAlgorithm()
ususally just returns the string you've provided earlier. The only thing you can do is to get the provider using getProvider()
and then lookup the defaults...
I would never go for any defaults (except for SecureRandom
defaults) as it is unspecified which defaults will be used for Java. Always specify the algorithm in full; your earlier string was fine.