3

我正在使用 javax.crypto 在 java 中进行 AES CBC 解密。我正在使用以下 Cipher 类方法:

  • public final void init (int opmode, Key key, AlgorithmParameters params)初始化方法,
  • final int update(byte[] input, int inputOffset, int inputLen, byte[] output)解密数据的方法,
  • 最后我调用该final int doFinal(byte[] output, int outputOffset)方法完成解密。

我的查询是这样的:我可以假设doFinal调用返回给我的数据大小总是小于或等于 AES 块大小吗?该文档将 doFinal 方法描述为:

“完成多部分转换(加密或解密)。处理可能在以前的更新调用中缓冲的任何字节。最终转换后的字节存储在输出缓冲区中。”</p>

但它没有说输出缓冲区最多包含一个数据块。虽然我知道这是 AES API 的一般行为,这是我的代码到目前为止所表现出的行为,但是这个假设会一直成立吗?

4

2 回答 2

3

一般来说(就像在课堂上一样Cipher)我不相信假设这一点是安全的。根据该方法的javadocsdoFinal

如果输出缓冲区太小而无法容纳结果,则会引发 ShortBufferException。在这种情况下,使用更大的输出缓冲区重复此调用。使用getOutputSize确定输出缓冲区的大小。

因此,如果您在调用 doFinal 方法的点“附近”分配输出缓冲区,那么调用getOutputSize并分配适当大小的缓冲区是有意义的。任务完成。

另一方面,如果您从“远处”传入一个缓冲区,该缓冲区被创建为正好是块大小,您可能会遇到更多麻烦。只要 getOutputSize 方法返回适当的大小,Cipher 实现返回大于块大小的输出是完全合法的(至少,根据 Java 类的公共接口)。

事实上,如果你在做 CBC 解密,那不是需要你把所有的块都传递给update方法吗?在这种情况下,您应该从 中获取完整的明文输出doFinal,而不仅仅是一个块?

于 2010-08-13T10:26:37.550 回答
0

一般来说,假设缓冲只针对一个块是不安全的。当您查看细节时,您可能会发现它取决于填充的类型。使用通常的“PKCS#5”填充,添加至少一个字节和最多n个字节(对于大小为n的块),因此解密系统可能会将自身限制为n个字节的缓冲。一些其他类型的填充稍微复杂一些,例如CTS需要2n字节的缓冲。Java 加密层目前似乎不支持 CTS,但可能会在未来的版本中添加。

Cipher.getOutputSize(len)给定额len外的输入字节,将为您提供最大输出大小。返回的值可能会比实际返回的值大一些,尤其是在解密时,因为它取决于解密时实际找到的填充字节。

可以肯定的是,解密消息的总长度不超过加密消息的总长度(对称加密不涉及数据压缩)。所以你可以维护两个计数器,一个用于输入数据字节(加密块),一个用于获得的输出数据字节;差异将是可以从doFinal(). 但这就是getOutputSize()无论如何。

于 2010-08-13T12:19:11.830 回答