0

我自己实现CBC模式。我使用 AES 作为每个 CBC 块的 E 函数。

这是我的加密代码:

public static List<Byte> encrypt(List<Byte> bytes, byte[] key) throws Exception {
    byte[] bytesArray = BytesConverter.toByteArray(bytes);

    SecretKey secretKey = new SecretKeySpec(key, AES);

    Cipher cipher = Cipher.getInstance(AES);
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    return BytesConverter.toByteList(cipher.update(bytesArray));
}

我使用update是因为我不想添加 AES 垫。我自己在CBC算法开始时的最后一个块上做。

当我想解密密文块时,我使用与 Cipher.DECRYPTION_MODE 相同的函数。

public static List<Byte> decrypt(List<Byte> bytes, byte[] key) throws Exception {
    byte[] bytesArray = BytesConverter.toByteArray(bytes);

    SecretKey secretKey = new SecretKeySpec(key, AES);

    Cipher cipher = Cipher.getInstance(AES);
    cipher.init(Cipher.DECRYPT_MODE, secretKey);

    return BytesConverter.toByteList(cipher.update(bytesArray));
}

问题在于,Cipher.update在解密模式下,该encrypt方法加密的输入返回空字节数组。

我很困惑。怎么了?

4

1 回答 1

2

You are missing a call to doFinal. Due to padding for ECB and CBC mode encryption, Cipher instances are required to buffer up to a block size - 1 of bytes, which will only be padded and encrypted (or decrypted and unpadded) in the doFinal() call, which releases the last part of ciphertext (or plaintext for decryption).

What you should do is to use "AES/ECB/NoPadding" and only doFinal instead of update to implement CBC for each block (although just update may also work, but it is not 100% specified that it should). This is identical to block encrypt of the underlying AES cipher. You could also use the lower level, lightweight (i.e.: direct, non-JCE) API of Bouncy Castle, which provides AES engines which just implement the block cipher itself.

于 2014-10-05T20:21:51.360 回答