2010-08-13 68 views
3

我正在使用javax.crypto在java中进行AES CBC解密。我使用下面的密码类方法:Cipher.do最终输出大小

  • 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的一般行为,而这是我的代码迄今为止所展示的行为,但是这种假设一直会持续吗?

+0

为了清楚起见,我需要多次调用更新函数,因为我以块的形式获取加密数据。我没有整个加密的数据,所以我不能做一个单一的调用doFinal来一步获得输出。 – vikas 2010-08-13 10:06:26

回答

3

一般(如在Cipher类的情况下)我不认为这是可以安全的假设这一点。由于每javadocsdoFinal方法:

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

所以,如果你分配输出缓冲器“近”在这里你调用doFinal方法的点,那么它会是有意义的调用getOutputSize并分配适当大小的缓冲区。任务完成。另一方面,如果您传入的“远处”缓冲区已创建为块大小,则可能会遇到更多麻烦。根据Java类的公共接口,只要getOutputSize方法返回适当的大小,Cipher实现返回大于块大小的输出将是完全合法的(至少,根据Java类的公共接口)。

事实上,如果你在做CBC解密,是不是要求你把所有的块都传给update方法?在这种情况下,您应该从doFinal得到完整的纯文本输出,而不仅仅是一个块?

+0

对'update'和'doFinal'使用'getOutputSize(固定输入大小)'的字节数组是安全吗? – 2012-04-09 13:16:07

+0

@Jin我不知道这是否会产生真正意义,因为它们是两回事。提供给'update'的字节数组应该是您要更新密码的数据的大小 - 它需要与* input *中的字节数相同。如果这肯定小于或等于'getOutputSize()',那么你*可以*重用相同的数组。实际上,尽管我怀疑这会比有帮助的更困惑。 – 2012-04-10 07:58:44

0

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

Cipher.getOutputSize(len)会给你最大的输出大小,给出len额外的输入字节。返回的值可能比实际返回的值大一些,特别是对于解密,因为它取决于在解密时实际会发现哪些填充字节。

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

+0

在我的情况下使用的填充只是'PKCS5Padding'。这是否意味着我可以假定最大输出尺寸是AES块尺寸? 我不能使用'Cipher.getOutputSize(len)'的原因是因为存储'doFinal()'输出的缓冲区被分配并传递给远离我不应该修改的代码的模块。并且分配的缓冲区的大小是AES块大小。 – vikas 2010-08-13 12:58:25

+0

你不能假设,但你可以检查它。如果块的大小为_n_,并且加密的消息由_k_块组成,则总解密的消息长度在_n(k-1)_和_(nk)-1_(含)之间。使用计数器,您可以知道(在运行时)剩余的缓冲数据在解密时是否适合尺寸为_n_的缓冲区。你不能假设_in advance_因为这不是Java密码体系结构的保证属性。 – 2010-08-13 13:35:22