AES。 javax.crypto.Cipher在解密模式下返回空数组

时间:2014-10-05 19:40:05

标签: java encryption cryptography aes cbc-mode

我自己实施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 pad。在CBC algorythm的开头,我自己做了最后一个块。

当我想解密密文块时,我使用与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方法加密的输入的空字节数组。

我很困惑。怎么了?

1 个答案:

答案 0 :(得分:2)

您错过了对doFinal的来电。由于ECB和CBC模式加密的填充,Cipher个实例需要缓冲一个块大小 - 1个字节,只会在doFinal()中填充和加密(或解密和取消填充) call,它释放密文的最后一部分(或用于解密的明文)。

你应该做的是使用"AES/ECB/NoPadding"而不是doFinal代替update为每个块实现CBC (尽管只是update也可以工作,但它不是100%指定它应该)。这与底层AES密码的块加密相同。您还可以使用Bouncy Castle的较低级别,轻量级(即:直接,非JCE)API,它提供AES 引擎,它只是实现分组密码本身。