Java的Cipher
类支持转换listed there。其中有几个NoPadding
变体:
我首先假设“填充”是指如果明文大小不是密码块大小的倍数,则用于填充最后一个明文块的方法。
但是在那种情况下,如何在“无填充”的情况下使用ECB或CBC这样的分组密码模式?假设我们使用AES/ECB/NoPadding
来加密250位消息。明文的第一块显然是消息的前128位。第二个纯文本块的最后6位是什么?
答案 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字节)。
纯文本大小是一起提供给update
和doFinal
方法的输入字节数。最后一个块之前的块的字节将在需要的地方进行缓冲-仅最终计数很重要。
摘自Cipher#doFinal
文档:
抛出:
......
IllegalBlockSizeException
-如果此密码是块密码,则没有请求填充(仅在加密模式下),并且此密码处理的数据的总输入长度不是块大小的倍数;或者该加密算法无法处理提供的输入数据。
...
请注意,这是我认为这是一个糟糕的描述:在解密期间,doFinal
无论使用哪种填充,都会抛出此异常(同样,仅适用于ECB和CBC模式)如果大小不是块大小的倍数。毕竟,只有在通过块密码和操作模式解密之后,才进行解填充。
当然,加密过程中ECB和CBC模式的输出应始终为块大小的倍数,这意味着密文在解密之前已被截断或以其他方式更改。
因为不需要GCM填充(在其中使用了CTR模式加密),所以NoPadding
是唯一可行的选择,并且会传输任意数量的数据-但同样是由{{1}加密的最小元素}是一个字节。即使GCM 算法是按位而不是字节指定的,但此实现不支持它。