Cipher类中的“ NoPadding”参数究竟能做什么?

时间:2020-01-26 23:19:23

标签: 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)

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

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

1 个答案:

答案 0 :(得分:1)

首先,您不能以任何方式直接向Cipher发送250位消息。原因是-与大多数运行时一样,该字节是您可以处理的最小数据量。如果要编码250位,则必须考虑对这些位进行字节编码(例如,通过指示您不使用的最后一个字节中的位,如对DER编码的ASN.1的值编码所执行的一样)定义的BIT STRING)。


“ DER BIT STRING”示例仅将11位设置为1:

05 FF E0

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


第二,即使输入将是 8位的倍数,除非ECB或CBC模式使用,否则您仍然无法使用NoPadding进行加密输入本身已经是块大小的倍数。如果您指定NoPadding,则实际上没有添加任何字节(甚至没有值00的字节),因此您将得到IllegalBlockSizeException 如果明文大小不是块大小的倍数(AES为16字节,DES&DES-EDE为8字节)。

纯文本大小是一起提供给updatedoFinal方法的输入字节数。最后一个块之前的块的字节将在需要的地方进行缓冲-仅最终计数很重要。


摘自Cipher#doFinal文档:

抛出:

......
IllegalBlockSizeException-如果此密码是块密码,则没有请求填充(仅在加密模式下),并且此密码处理的数据的总输入长度不是块大小的倍数;或者该加密算法无法处理提供的输入数据。
...

请注意,这是我认为这是一个糟糕的描述:在解密期间,doFinal 无论使用哪种填充,都会抛出此异常(同样,仅适用于ECB和CBC模式)如果大小不是块大小的倍数。毕竟,只有在通过块密码和操作模式解密之后,才进行解填充。

当然,加密过程中ECB和CBC模式的输出应始终为块大小的倍数,这意味着密文在解密之前已被截断或以其他方式更改。


因为不需要GCM填充(在其中使用了CTR模式加密),所以NoPadding是唯一可行的选择,并且会传输任意数量的数据-但同样是由{{1}加密的最小元素}是一个字节。即使GCM 算法是按位而不是字节指定的,但此实现不支持它。

相关问题