Cipher.do最终输出大小
我正在使用 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 的一般行为,也是我的代码到目前为止所表现出的行为,但是这个假设总是成立吗?
I am doing AES CBC decryption in java using javax.crypto . I am using the following Cipher class methods:
public final void init (int opmode, Key key, AlgorithmParameters params)
method for initialization,final int update(byte[] input, int inputOffset, int inputLen, byte[] output)
method for decrypting the data,- and finally I call the
final int doFinal(byte[] output, int outputOffset)
method to finish the decryption.
My query is this: Can I assume that the size of the data returned to me by the doFinal
call would always be less than or equal to the AES Block Size? The documentation describes the doFinal method as:
“Finishes a multi-part transformation
(encryption or decryption). Processes
any bytes that may have been buffered
in previous update calls. The final
transformed bytes are stored in the
output buffer.”
But it nowhere says that the output buffer would contain at most one block of data. Though I understand that this is the general behaviour of AES APIs, and this is the behaviour my code has exhibited till now, but would this assumption always hold?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在一般中(如在
Cipher
类的上下文中),我不认为这样假设是安全的。根据 javadocs 对于该doFinal
方法:因此,如果您在调用 doFinal 方法的点“附近”分配输出缓冲区,则调用 getOutputSize 并分配适当大小的缓冲区是有意义的。工作完成了。
另一方面,如果您从“远处”传入一个缓冲区,该缓冲区是按照块大小创建的,那么您可能会遇到更多麻烦。只要 getOutputSize 方法返回适当的大小,Cipher 实现返回大于块大小的输出就是完全合法的(至少根据 Java 类的公共接口)。
事实上,如果您正在进行 CBC 解密,是否需要将所有块传递给
update
方法?在这种情况下,您应该从 doFinal 获取完整的明文输出,而不仅仅是单个块?In general (as in, in the context of the
Cipher
class) I don't believe it would be safe to assume this. As per the javadocs for thatdoFinal
method:So if you're allocating the output buffer "near" the point where you call the doFinal method, then it would make sense to call
getOutputSize
and allocate an appropriately-sized buffer. Job done.On the other hand, if you're passing in a buffer from "far away" that was created to be exactly the block size, you might be in more trouble. It would be perfectly legal (at least, according to the public interface of the Java class) for a Cipher implementation to return an output larger than the block size, so long as the getOutputSize method returns the appropriate size.
In fact, if you're doing CBC decryption, doesn't that require you to pass in all of the blocks to the
update
method? In which case, you should get the full plaintext output back fromdoFinal
, not just a single block?一般来说,假设缓冲仅针对一个块是不安全的;当您查看详细信息时,您可能会发现这取决于填充的类型。使用通常的“PKCS#5”填充,至少添加一个字节,最多添加 n 个字节(对于大小为 n 的块),因此解密系统可能会限制自身到 n 字节的缓冲。一些其他类型的填充有点复杂,例如 CTS 需要2n 缓冲字节。 Java 加密层目前似乎不支持 CTS,但可能会在未来版本中添加。
给定
len
额外的输入字节,Cipher.getOutputSize(len)
将为您提供最大输出大小。返回的值可能比实际返回的值稍大,尤其是在解密时,因为它取决于解密时实际找到的填充字节。可以安全地假设的是,解密消息的总长度不大于加密消息的总长度(对称加密不涉及数据压缩)。因此,您可以维护两个计数器,一个用于输入数据字节(加密块),另一个用于获得的输出数据字节;差异将是从
doFinal()
可以获得的最大范围。但这就是getOutputSize()
所做的事情。Generally speaking, it is not safe to assume that buffering is for one block only; and when you look at the details, you may see that it depends on the type of padding. With the usual "PKCS#5" padding, at least one byte and at most n bytes (for blocks of size n) are added, so the decryption system may limit itself to n bytes of buffering. Some other types of padding are a bit more complex, e.g. CTS requires 2n bytes of buffering. The Java cryptographic layer does not seem to support CTS right now, but this may be added in a future version.
Cipher.getOutputSize(len)
will give you the maximum output size, givenlen
additional input bytes. The returned value may be somewhat larger than what will be actually returned, especially with decryption, since it depends on what padding bytes will be actually found upon decryption.What is safe to assume is that the total decrypted message length is no longer than the total encrypted message length (symmetric encryption does not involve data compression). So you may maintain two counters, one for the input data bytes (the encrypted blocks) and one for the obtained output data bytes; the difference will be a maximum bound for what can be obtained from the
doFinal()
. But that's whatgetOutputSize()
does anyway.