0

我的问题是 - 如何确定输出密文的长度?

我隐约知道输出长度必须是所使用密码的块大小的倍数。但这是否意味着:

  1. 如果输入数据的长度是密码块大小的倍数,那么输出长度将与输入长度相同吗?
  2. 如果输入数据的长度不是密码块大小的倍数,那么输出长度将是输入长度+一个块大小?

谢谢!

4

2 回答 2

2

罗伯特关于密文大小是正确的,这取决于密码模式和填充,可能还有块模式。

如果您在流模式下使用密码(例如 CTR),则密文大小与明文大小相同。如果您使用诸如 GCM 之类的身份验证模式,那么您必须至少使用身份验证标签来增加它。您还可以使用 CBC 模式和密文窃取 (CTS) 来摆脱填充开销,但这仅适用于两个或更多块。

现在让我们假设 CBC 模式的 PKCS#5/7 兼容填充,这是目前最常用的模式。在这种情况下,您的明文至少填充了一个填充字节(否则 unpadding 无法区分例如用单个01值填充字节填充的明文和明文 - 可除以块大小 - 以01值字节结尾)。这意味着如果明文已经块对齐,则添加整个块。

当然,如果明文不是块对齐的,那么 PKCS#7 填充只需要填充最后一个块。因此,在这种情况下,block size添加了 1 个字节。于是计算变为:

L密文=(L明文/L)*(L+1)

其中 L明文/ L被四舍五入(在大多数编程语言中进行整数计算时通常如此)。

现在让我们假设 AES,它的块大小总是 16 字节:

  0 bytes -> 16 bytes
  1 byte  -> 16 bytes
  2 bytes -> 16 bytes
 ...
 15 bytes -> 16 bytes
 16 bytes -> 32 bytes
 17 bytes -> 32 bytes
 ...

请注意,有相当多的实现使用非标准化填充。一个例子是 PHP 中的 mcrypt 库(您可能可以使用 mcrypt 作为密码学中任何不良做法的基础)。这使用零填充,因此它只是填充00有价值的字节,直到明文块对齐。在这种情况下,结果大小可以这样计算:

L密文= (L明文/ L- 1) * (L+ 1)

显然,当您将它与任何不期望非标准化零填充的实现一起使用时,或者当明文可能以一个或多个00有价值的字节结尾时,您会遇到麻烦。

最后说明:某些语言(例如 Java Cipher)具有检索块大小甚至从加密实现中得到的密文的方法。在你开始自己实现之前检查 API 永远不会有坏处。

在撰写本文时,维基百科对填充模式有很好的解释。

于 2013-03-08T12:15:21.147 回答
1

输出密文的长度取决于块长度、密码模式以及是否使用填充。

有一些像 CTS 这样的密码模式可以创建与输入相等的密码输出长度,即使使用分组密码也是如此。

关于1:如果输入数据的长度是密码块大小的倍数并且使用了填充,那么输出长度将大一个块,因为您需要至少一个字节来指定填充长度。

关于2:输出长度必须是块长度的倍数,因此它是输入长度+(输入长度​​模块长度)

于 2013-03-08T10:50:01.580 回答