Cipher.doFinal输出大小

时间:2010-08-13 09:56:09

标签: java aes finalize encryption

我正在使用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方法描述为:

  

“完成多部分转型   (加密或解密)。流程   任何可能已缓冲的字节   在之前的更新调用中。决赛   转换后的字节存储在   输出缓冲区。“

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

2 个答案:

答案 0 :(得分:3)

general 中(例如,在Cipher类的上下文中)我不相信这样做是安全的。根据{{​​1}}方法的javadocs

  

如果输出缓冲区太小而无法保存结果,则抛出ShortBufferException。在这种情况下,使用更大的输出缓冲区重复此调用。使用getOutputSize确定输出缓冲区应该有多大。

因此,如果您将输出缓冲区“分配”在调用doFinal方法的位置附近,则调用doFinal并分配适当大小的缓冲区是有意义的。完成工作。

另一方面,如果你从一个创建的“远离”缓冲区中传入一个缓冲区,那么你可能会遇到更多问题。只要getOutputSize方法返回适当的大小,Cipher实现返回大于块大小的输出就完全合法(至少,根据Java类的公共接口)。

事实上,如果您正在进行CBC解密,那么是否要求您将所有块传递给getOutputSize方法?在这种情况下,您应该从update获取完整的纯文本输出,而不仅仅是一个块?

答案 1 :(得分:0)

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

在给定Cipher.getOutputSize(len)个额外输入字节的情况下,

len将为您提供最大输出大小。返回的值可能比实际返回的值稍大,特别是在解密时,因为它取决于在解密时实际找到的填充字节。

可以安全地假设总解密消息长度不超过总加密消息长度(对称加密不涉及数据压缩)。因此,您可以维护两个计数器,一个用于输入数据字节(加密块),另一个用于获取的输出数据字节;差异将是doFinal()可以获得的最大界限。但无论如何,这就是getOutputSize()所做的。