I have a block of ciphertext that was created using the JCE algorithim \"PBEWithSHA256And256BitAES-CBC-BC\". The provider is BouncyCastle. What I\'d like to do it decrypt th
There were a few problems with your decrypt method:
private static byte[] decrypt(final byte[] bytes, final char[] password, final byte[] salt) throws DataLengthException, IllegalStateException, InvalidCipherTextException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
final PBEParametersGenerator keyGenerator = new PKCS12ParametersGenerator(new SHA256Digest());
keyGenerator.init(PKCS12ParametersGenerator.PKCS12PasswordToBytes(password), salt, 20);
final CipherParameters keyParams = keyGenerator.generateDerivedParameters(256, 128);
final BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()), new PKCS7Padding());
cipher.init(false, keyParams);
final byte[] processed = new byte[cipher.getOutputSize(bytes.length)];
int outputLength = cipher.processBytes(bytes, 0, bytes.length, processed, 0);
outputLength += cipher.doFinal(processed, outputLength);
final byte[] results = new byte[outputLength];
System.arraycopy(processed, 0, results, 0, outputLength);
return results;
}
The main problems were the way you were carrying out the decryption without using a block cipher and the missing IV size to the generateDerivedParameters
method. I saw the first problem pretty quickly, the 2nd one was much less obvious. I only discovered that one through looking at a Bouncy Castle test called PBETest.
I noticed that your encryption method accepts a password as a char array but the decrypt accepts password as bytes. In Java chars are 16-bit while bytes are 8-bit. This could result in different keys for encrypt/decrypt and perhaps explain the issues with gibberish decrypted results?
I tried this and it seemed to work. Borrowed heavily from the BC class org.bouncycastle.jce.provider.test.PBETest
private byte[] decryptWithLWCrypto(byte[] cipher, String password, byte[] salt, final int iterationCount)
throws Exception
{
PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA256Digest());
char[] passwordChars = password.toCharArray();
final byte[] pkcs12PasswordBytes = PBEParametersGenerator
.PKCS12PasswordToBytes(passwordChars);
pGen.init(pkcs12PasswordBytes, salt, iterationCount);
CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());
ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
aesCBC.init(false, aesCBCParams);
PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC,
new PKCS7Padding());
byte[] plainTemp = new byte[aesCipher.getOutputSize(cipher.length)];
int offset = aesCipher.processBytes(cipher, 0, cipher.length, plainTemp, 0);
int last = aesCipher.doFinal(plainTemp, offset);
final byte[] plain = new byte[offset + last];
System.arraycopy(plainTemp, 0, plain, 0, plain.length);
return plain;
}
It's not trivial to generate the key exactly as the JCE counterparts. I just briefly browsed your code. Found at least one discrepancy. JCE uses PKCS12 generator but you use PKCS5S1.
I am not surprised if there are other differences. You need to compare your code against BC source.