AES/CBC 和 AES/ECB 加密后的数据大小
Posted
技术标签:
【中文标题】AES/CBC 和 AES/ECB 加密后的数据大小【英文标题】:Size of data after AES/CBC and AES/ECB encryption 【发布时间】:2011-03-18 01:28:42 【问题描述】:我想知道 AES 加密后的数据大小,这样我就可以避免缓冲我的 AES 后数据(在磁盘或内存上)主要是为了知道大小。
我使用 128 位 AES 和 javax.crypto.Cipher
和 javax.crypto.CipherInputStream
进行加密。
对不同输入大小进行的一些测试表明,如下计算的后加密大小是正确的:
long size = input_Size_In_Bytes;
long post_AES_Size = size + (16 - (size % 16));
但我不确定上述公式是否适用于所有可能的输入大小。
有没有一种方法可以在应用 AES 加密后计算数据的大小 - 无需预先缓冲加密数据(在磁盘或内存上)以了解其加密后的大小?
【问题讨论】:
【参考方案1】:long post_AES_Size = size + (16 - (size % 16));
cipherLen = (clearLen/16 + 1) * 16
@zz-coder 和@OP 提到的是一样的。
int(clearLen/16) + 1) * 16
= ((clearLen - clearLen % 16) / 16 + 1) * 16
= clearLen - clearLen % 16 + 16;
= clearLen + (16 - clearLen % 16)
【讨论】:
【参考方案2】:如果您的输入长度小于 int 的最大大小,您可以使用 Cipher.getOutputSize(int)
【讨论】:
【参考方案3】:一般来说,对于分组密码加密:
CipherText = PlainText + Block - (PlainText MOD Block)
密文大小被计算为明文的大小扩展到 下一个区块。如果使用填充并且明文的大小是 块大小的精确倍数,一个包含填充的额外块 信息将被添加。
AES 使用 16 字节的块大小,这会产生:
密文 = 纯文本 + 16 - (纯文本 MOD 16)
来源: http://www.obviex.com/articles/CiphertextSize.pdf
注意:
-
CipherText 和PlainText 分别代表密文的大小和纯文本的大小。
【讨论】:
【参考方案4】:AES 具有 16 字节的固定块大小,与密钥大小无关。假设您使用 PKCS 5/7 填充,请使用此公式,
cipherLen = (clearLen/16 + 1) * 16;
请注意,如果明文是块大小的倍数,则需要一个全新的块来填充。假设您的明文是 16 个字节。密文将占用 32 个字节。
您可能希望将 IV(初始向量)与密文一起存储。在这种情况下,您需要为 IV 添加 16 个字节。
【讨论】:
为什么需要为 16 字节的明文添加一个全新的块。它已经是 16 的倍数。在此先感谢 没有至少一位填充,块没有端点。 @Durin 的问题很好。原因是没有区分明文的方法,例如10 0F 0E ... 02 01
来自 10 0F 0E ... 02
的填充明文 + 填充 01
。这就是为什么总是执行填充。如果明文大小已知“带外”,或者已知该值末尾不包含00
(例如对于ASCII字符串),有时会使用零填充到块大小。
用零填充和用空格填充不是标准化模式。 Bouncy 总是填充,即使是零。 php 没有。用零填充和用空格填充都不是确定性 填充模式。它们起作用的原因是明文(作为字节)具有已知长度,或者明文具有预定格式(例如,只是可打印的 ASCII 字符)。但是,如果不满足这些条件,零填充可能会严重失败;例如如果 UTF16LE 文本以 00
结尾(很可能)。换句话说,这些填充模式存在,但它们确实对输入施加了限制
@Abraham 不,那是因为答案确实是错误的。这只是计算上限的一种快速方法。对于 Java,您当然可以质疑您的 Cipher
实例的正确长度(现在)。在 *** 上,upvotes 几乎没有任何意义。【参考方案5】:
如果数据大小至少等于块大小,则有一些存储加密信息的方法可以避免任何填充。一个小困难是,如果允许数据大小小于块大小,并且如果必须能够重建数据的精确大小,即使是小块,输出也必须至少比块大小大一位。输入,[i]不管[/i]数据大小。
要理解这个问题,请意识到有 256^N 个可能的文件长度为 N 字节,并且长度不超过 N 字节的可能文件的数量是 256^N 加上可能的文件数量不超过长度超过 N-1 个字节(有 1 个可能的文件长度为零字节,257 个可能的文件长度不超过 1 个字节)。
如果块大小为 16 字节,则将有 256^16 + 256^14 + 256^13 等可能的输入文件长度不超过 16 字节,但只有 256^16 个可能的输出文件长度不超过长度超过 16 个字节(因为输出文件不能短于 16 个字节)。所以至少一些可能的 16 字节输入文件必须增长。假设它们将变为 17 个字节。有 256^17 个可能的 17 字节输出文件;如果其中任何一个用于处理 16 字节或更少的输入,则没有足够的可用空间来处理所有可能的 17 字节输入文件。无论输入有多大,该大小或更大的一些文件都必须增长。
【讨论】:
【参考方案6】:这取决于您使用 AES 的模式。对于大多数面向块的模式,例如 ECB 和 CBC,您所拥有的都是准确的。 OTOH,在 CFB 模式下(例如),您基本上只是使用 AES 来生成字节流,您可以将其与输入字节进行异或。在这种情况下,输出的大小可以保持输入的大小,而不是像上面给出的那样向上舍入到下一个块大小。
【讨论】:
【参考方案7】:AES 在 128 位(16 字节)块中工作,并将明文块转换为相同长度的密文块。如果它小于 16 个字节,它会填充最后一个块,因此您的公式看起来是正确的。
【讨论】:
【参考方案8】:AES 作为分组密码,不会改变大小。输入大小始终是输出大小。
但是 AES 作为分组密码,要求输入是块大小(16 字节)的倍数。为此,像流行的PKCS5 一样使用填充方案。所以答案是加密数据的大小取决于使用的填充方案。但同时所有已知的填充方案将四舍五入到下一个模块 16 大小(大小 AES 具有 16 字节块大小)。
【讨论】:
有些填充方案不需要改变数据大小。 @usr 不,有 操作模式 不需要更改数据大小(尽管通常需要 IV 和/或身份验证标签作为开销)。根据定义,填充模式使密码的数据输入更大。【参考方案9】:AES 密码始终适用于 16 字节(128 位)块。如果输入字节数不是 16 的精确倍数,则对其进行填充。这就是为什么 16 似乎是您计算中的“幻数”。你所拥有的应该适用于所有输入大小。
【讨论】:
请注意,始终添加至少一个填充字节,即使输入长度是 16 的精确倍数。以上是关于AES/CBC 和 AES/ECB 加密后的数据大小的主要内容,如果未能解决你的问题,请参考以下文章
AES共有ECB,CBC,CFB,OFB,CTR五种模式分别有啥区别