java - "NoPadding"参数在 Cipher 类中到底有什么作用?

标签 java encryption cryptography padding block-cipher

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

  • AES/CBC/NoPadding (128)
  • AES/ECB/NoPadding (128)
  • AES/GCM/NoPadding (128)
  • DES/CBC/NoPadding (56)
  • DES/ECB/NoPadding (56)
  • DESede/CBC/NoPadding (168)
  • DESede/ECB/NoPadding (168)

我首先假设这里的“填充”是指用于填充最后一个明文 block 的方法,如果明文的大小不是密码 block 大小的倍数。

但在这种情况下,如何才能在“无填充”的情况下使用 ECB 或 CBC 等分组密码模式呢?假设我们使用 AES/ECB/NoPadding 来加密 250 位消息。明文的第一个 block 显然是消息的前 128 位。第二个明文 block 的最后 6 位是多少?

最佳答案

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

<小时/>

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

05 FF E0

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

<小时/>

其次,即使输入 8 位的倍数,您仍然无法使用NoPadding 进行加密。对于 ECB 或 CBC 模式除非输入本身已经是 block 大小的倍数。如果指定NoPadding那么确实没有添加任何字节(甚至没有 00 有值(value)的字节),所以你会得到一个 IllegalBlockSizeException 如果明文大小不是 block 大小的倍数(AES 为 16 字节,DES 和 DES-EDE 为 8 字节)。

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

<小时/>

来自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 将抛出此异常。如果大小不是 block 大小的倍数,则无论使用什么填充(同样,仅适用于 ECB 和 CBC 模式)。毕竟,填充仅在通过分组密码和操作模式解密后才会发生。

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

<小时/>

对于GCM来说不需要padding(内部使用了CTR模式加密),所以NoPadding是唯一现实的选择,任何数量的数据都可以 - 但同样是由 Cipher 加密的最小元素是一个字节。尽管 GCM 算法是以位而不是字节为单位指定的,但此实现并不支持它。

关于java - "NoPadding"参数在 Cipher 类中到底有什么作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59923645/

相关文章:

java - 二维数组列表

java - 如何从对象列表中删除重复项

javax.mail.messagingException 连接超时 连接

java - 将坐标从 3D 场景转换为 2D 叠加

c - OpenSSL EVP_DecryptFinal_ex 在输出缓冲区末尾生成垃圾

java - 在Android/Java平台上加密共享 key

c# - SHA256 的 RSACryptoServiceProvider.SignHash 返回 128 字节而不是 32?

java - perl Digest::MD5 md5($data) 和 java MessageDigest.getInstance ("MD5").digest($data) 的输出不同

mysql - 从 node.js 将二进制文件插入 MySQL

java - ios 以编程方式创建证书请求