"NoPadding" 参数在 Cipher class 中究竟做了什么?

What exactly does the "NoPadding" parameter do in the Cipher class?

Java 的 Cipher class 支持转换 listed there。其中有几个 NoPadding 变体:

起初我假设 "padding" 这里的意思是用于填充最后一个明文块的方法,如果明文的大小不是密码块大小的倍数。

但在那种情况下,ECB 或 CBC 等分组密码模式如何与 "no padding" 一起使用?假设我们使用 AES/ECB/NoPadding 来加密一条 250 位的消息。明文的第一块显然是消息的前 128 位。第二个明文块的后6位是多少?

嗯,首先,您不能直接提供 Cipher - 在任何模式下 - 250 位的消息。原因是 - 与大多数运行时一样 - 字节是您可以处理的最小数据量。如果你想编码 250 位,你将不得不考虑以字节为单位的这些位的编码(例如,通过指示你不使用的最后一个字节中的位,就像对 DER 编码的 ASN.1 的值编码执行的那样)定义的位串)。


仅 11 位设置为 1 的 DER BIT STRING 示例:

05 FF E0

此处最后一个字节中有 5 个未使用的位(设置为值 0)。所以第一个字节只是牺牲来表明这个事实——它不是值的一部分。


其次,即使输入 8 位的倍数,您仍然无法使用 NoPadding 对 ECB 或 CBC 模式进行加密 unless 输入本身已经是块大小的倍数。如果您指定 NoPadding 那么实际上没有添加任何字节(甚至没有 00 值字节)所以您将获得 IllegalBlockSizeException if 明文大小不是块大小的倍数(AES 为 16 字节,DES 和 DES-EDE 为 8 字节)。

明文大小是提供给 updatedoFinal 方法的输入字节的总和。最后一个块之前的块的字节将在需要时进行缓冲 - 只有最终计数很重要。


来自 Cipher#doFinal 文档:

throws:

    ...
    IllegalBlockSizeException - if this cipher is a block cipher, no padding has been requested (only in encryption mode), and the total input length of the data processed by this cipher is not a multiple of block size; or if this encryption algorithm is unable to process the input data provided.
    ...

请注意,在我看来,这是一个糟糕的描述:在解密期间,此异常将由 doFinal 抛出,而不管 使用的填充(再次,仅适用于 ECB 和 CBC 模式)如果大小不是块大小的倍数。毕竟只有在分组密码和操作模式解密后才会发生填充。

当然,加密期间 ECB 和 CBC 模式的输出应该始终是块大小的倍数,因此这意味着密文在解密之前被截断或以其他方式更改。


对于 GCM 不需要填充(在其中使用 CTR 模式加密),因此 NoPadding 是唯一现实的选择,并且任何数量的数据都可以 - 但同样是要由 [= 加密的最小元素11=] 是一个字节。尽管 GCM 算法 是以位而不是字节指定的,但此 实现 不支持它。