Decrypting aes-256-cbc using bouncycastle

2019-06-05 03:38发布

问题:

New to bouncyCastle, any help appreciated. I am trying to decrypt a file encrypted by third party on my system using bounncycastle java API. It seems to decrypt file fine except for the blob of junk data at the beginning on the decrypted file.Code below

PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
                    new AESEngine()));
            CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(DatatypeConverter.parseHexBinary(keyInfo.getKey())),
                    DatatypeConverter.parseHexBinary(keyInfo.getInitializationVector()));
            aes.init(false, ivAndKey);

            byte[] decryptedBytes = cipherData(aes, Base64.decodeBase64(inputStreamToByteArray(new FileInputStream(encryptedFile))));

            return new ByteArrayInputStream(decryptedBytes);

private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data)
        throws Exception {
    int minSize = cipher.getOutputSize(data.length);
    byte[] outBuf = new byte[minSize];
    int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
    int length2 = cipher.doFinal(outBuf, length1);
    int actualLength = length1 + length2;
    byte[] result = new byte[actualLength];
    System.arraycopy(outBuf, 0, result, 0, result.length);
    return result;
}
private byte[] inputStreamToByteArray(InputStream is) throws IOException {

    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    int numberRead;
    byte[] data = new byte[16384];

    while ((numberRead = is.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, numberRead);
    }

    buffer.flush();

    return buffer.toByteArray();
}

Decrypted data blob looks fine except for the beginning "???&??ovKw?????C??:?8?06??85042| | "

The openssl command to decrypt the file works fine command below. In fact I am using the key and iv printed out by openssl when decrypting.

openssl aes-256-cbc -d -salt -in encryptedfile.txt -pass pass:password -a -p

回答1:

The solution is simple: skip the first 16 bytes of the ciphertext blob. The encrypted blob starts with a magic (you can try and read the first 8 bytes as ASCII text), then 8 bytes of random salt that are used together with the password to derive the key and the IV (using an OpenSSL proprietary password hashing mechanism called EVP_BytesToKey).

Because the previous block is used as a vector for the next block in CBC the followup block of 16 bytes is also affected, giving you 32 random bytes at the start. Instead byte 16 to 31 should have been XOR'ed with the IV.

Here's a Java implementation of BytesToKey posted by using my old nickname.