我的问题是 - 如何确定输出密文的长度?
我隐约知道输出长度必须是正在使用的密码的块大小的倍数。但这是否意味着:
谢谢!
答案 0 :(得分:2)
罗伯特关于密文大小是正确的,取决于密码模式和填充,以及可能的块模式。
如果在流模式下使用密码(例如CTR),则密文大小与明文大小相同。如果您使用经过身份验证的模式(如GCM),则必须至少使用身份验证标记来增加此模式。您也可以使用CBC模式将密文窃取到(CTS)以消除填充开销,但这只适用于两个或更多块。
现在让我们假设CCS模式的PKCS#5/7兼容填充,这是目前最常用的模式。在这种情况下,您的明文至少填充一个填充字节(否则,无法填充无法区分例如用单个01
值填充字节填充的明文和明文 - 可以按块大小分割 - 以{{结尾1}}有价值的字节)。这意味着如果明文已经块对齐,则会添加整个块。
当然,如果明文不是块对齐的,那么PKCS#7填充只需要填充最后一个块。因此,在这种情况下,添加1到01
个字节。所以计算结果如下:
L ciphertext =(L 明文 / L block )*(L block + 1)
其中L 明文 / L 块向下舍入(与大多数编程语言中的整数计算一样)。
现在假设AES,其块大小始终为16字节:
block size
请注意,有一些实现使用非标准化填充。一个例子是PHP中的mcrypt库(您可以使用mcrypt作为加密中任何不良做法的基础)。这使用零填充,因此它只是填充 0 bytes -> 16 bytes
1 byte -> 16 bytes
2 bytes -> 16 bytes
...
15 bytes -> 16 bytes
16 bytes -> 32 bytes
17 bytes -> 32 bytes
...
值的字节,直到明文被块对齐。在这种情况下,结果大小可以这样计算:
L ciphertext =(L 明文 / L block - 1)*(L block + 1)
当你在任何不期望非标准化零填充的实现中使用它时,或明文可能以一个或多个00
值的字节结束时,显然会遇到麻烦。
最后注意事项:某些语言(例如Java 00
)具有检索块大小甚至是加密实现中产生的密文的方法。在开始自己实现之前检查API永远不会受到伤害。
维基百科在撰写本文时对padding modes有很好的解释。
答案 1 :(得分:1)
输出密文的长度取决于块长度,密码模式以及是否使用填充。
像CTS这样的密码模式可以创建一个等于输入的密码输出长度,即使使用分组密码也是如此。
关于1: 如果输入数据的长度是密码块大小的倍数并且使用了填充,则输出长度将比一个块大一个,因为您需要至少一个字节来指定填充长度。
关于2:输出长度必须是块长度的倍数,因此它是输入长度+(输入长度 mod 块长度)