Decrypting RSA with Java

In a recent Java project (a *small* departure from my normal VB.NET development), I was attempting to use RSA to decrypt a value stored in one of our databases, but was running into some trouble. When I used Java’s native RSA Cipher (available in Java 1.5+), I could decrypt the value without any issues, but when I switched to Bouncycastle, I would get gibberish. Since I was doing the decryption from inside an Oracle database, the only version of Java available was 1.4.2, which doesn’t have a default RSA provider, leaving Bouncycastle as the only option.

The decryption didn’t fail or throw an exception – it always succeeded – but the resulting decrypted byte array was completely different between the two providers. In Java’s native RSA, it was 32 bytes (as it should be), but in Bouncycastle, it was 128 bytes (the same length as the input, interestingly).

In the end, it turned out that Java’s default RSA implementation is “RSA/None/PKCS1Padding”, whereas BC’s is “RSA/None/NoPadding”. Changing BC’s version of the Cipher.getInstance line in my code to explicitly specify the new padding resolved my issue:

    RSADecrypter = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");

Here’s the original code (Line 10 is the one to switch out):

Cipher RSADecrypter;

// Here's the flag for choosing which provider to use
Boolean UseBouncyCastle = Boolean.TRUE;

// Choose between Java and BouncyCastle
if (UseBouncyCastle == Boolean.TRUE)
{
    Security.addProvider(new BouncyCastleProvider());
    RSADecrypter = Cipher.getInstance("RSA", "BC");
} else
{
    RSADecrypter = Cipher.getInstance("RSA");
}

// Initialize the Cipher using our the first key in the keystore
// This step works fine for both providers
RSADecrypter.init(Cipher.DECRYPT_MODE, keystore.getKey("1", PrivateKeyPassword.toCharArray()));

// Decrypt first 128 bytes of the array - here's the problem
// Java RSA gives 32 byte result, BouncyCastle gives 128 bytes of randomness
aegEncryptionKey = RSADecrypter.doFinal(binaryDataEncrypted,0,128);

More related reading:

How to check the java version
Bouncycastle’s default crypto
Java’s default crypto