为什么cipher.getOutputSize()返回值高于要求?

时间:2017-03-28 07:00:14

标签: java encryption bouncycastle

我试图解密使用AES256 CBC加密的文件,这是我的代码:

PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));
byte[] outBuf = new byte[cipher.getOutputSize(data.length)];
int processed = cipher.processBytes(data, 0, data.length, outBuf, 0);
processed += cipher.doFinal(outBuf, processed);

这很简单,但是cipher.getOutputSize(data.length)总会返回一个大于所需值的值。我总是在缓冲区末尾有一些奇怪的字符。

我试图解密两个html文件,这就是它们的结尾:

</HTML>����������������
// Processed: 9304 Size: 9312

</body></html>��������
// Processed: 636 Buffer size: 640

所以额外的字节大小不一致,我不能只是减少一些&#39;。

在计算输出数组的大小时,我做错了什么?

2 个答案:

答案 0 :(得分:1)

它与填充有关。

AES逐块加密,每个块必须长128位。将一些不可分割的数据传入128位的块意味着最后的明文块必须填充,直到它的大小为128位。

getOutputSize正在向您返回密文加密时的大小。请记住,明文填充然后加密,因此输出大小与输出大小相同。您可以看到这一点,因为636 mod 16 = 12636 - 12 + 16 = 640。例如。它会向上舍入到最接近的16的倍数,因为这是加密前包含多少额外的填充字节。

由于您在解密时使用此数组,因此您需要分配 所需的字节,因此该数组大于所需数组。 getOutputSize可以用于加密和解密,只要您知道它是最坏情况的&#34;缓冲区分配的场景。

答案 1 :(得分:1)

TL; DR:getOutputSize()让你知道要分配的大小缓冲区(最坏的情况),processBytes / doFinal的返回值告诉你实际使用了多少缓冲区(确切)。

您正在使用PaddedBufferedBlockCipher进行解密(上面的代码默认为PKCS7填充)。 getOutputSize()无法确定输出明文的确切数量,直到它实际看到最后一个块的解密数据,因此返回的值将是一个上限,这就是为什么processBytes / doFinal的返回值让你知道如何实际输出很多。

为简单起见,PaddedBufferedBlockCipher还忽略了所使用的特定填充方案的细节 - 它只假设最后一个块可能包含一些将被删除的填充。

&out39f&#39;结束时未使用的字节不是由密码写的。特别是,它们不包含填充。大概是&#34;奇怪的角色&#34;是来自数组初始化的零字节。