我正在使用javax.crypto在java中进行AES CBC解密。我使用以下密码类方法:
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的一般行为,这也是我的代码到目前为止所表现出来的行为,但这种假设是否总是成立的呢?
发布于 2010-08-13 10:26:37
通常(在Cipher类的上下文中),我不认为这样做是安全的。根据该javadocs方法的doFinal:
如果输出缓冲区太小,无法保存结果,则会引发ShortBufferException。在本例中,使用更大的输出缓冲区重复此调用。使用getOutputSize确定输出缓冲区的大小。
因此,如果您正在“靠近”调用doFinal方法的点分配输出缓冲区,那么调用getOutputSize并分配适当大小的缓冲区是有意义的。工作完成了。
另一方面,如果您从“远远”传入一个缓冲区,该缓冲区被创建为与块大小完全相同的缓冲区,那么您可能会遇到更多的麻烦。只要getOutputSize方法返回适当的大小,密码实现返回大于块大小的输出是完全合法的(至少根据Java类的公共接口)。
实际上,如果您正在执行CBC解密,这不需要将所有块传递给update方法吗?在这种情况下,您应该从doFinal获得完整的明文输出,而不仅仅是一个块?
发布于 2010-08-13 12:19:11
一般来说,假设缓冲区只用于一个块是不安全的;当您查看详细信息时,您可能会看到它取决于填充的类型。使用通常的"PKCS#5“填充,至少会添加一个字节和最多n个字节(对于大小为n的块),因此解密系统可能会将自己限制为n字节的缓冲。其他一些类型的填充要复杂一些,例如CTS需要2n字节的缓冲。Java加密层现在似乎不支持CTS,但这可能会添加到将来的版本中。
给定Cipher.getOutputSize(len)额外的输入字节,len将给出最大输出大小。返回的值可能比实际返回的要大一些,特别是解密时,因为它取决于解密时实际会找到哪些填充字节。
安全的假设是,总解密消息长度不大于总加密消息长度(对称加密不涉及数据压缩)。因此,您可以维护两个计数器,一个用于输入数据字节(加密块),另一个用于获取的输出数据字节;差异将是从doFinal()获得的最大界限。但无论如何,这就是getOutputSize()所做的。
https://stackoverflow.com/questions/3475761
复制相似问题