AES 应该使用啥样的填充?
Posted
技术标签:
【中文标题】AES 应该使用啥样的填充?【英文标题】:What kind of padding should AES use?AES 应该使用什么样的填充? 【发布时间】:2012-11-14 08:48:18 【问题描述】:我已经实现了 AES 加密(作业),但我偶然发现了填充消息的问题。
如果我的消息是这样的字节数组:
public byte[] encrypt(byte[] message)
int size = (int) Math.ceil(message.length / 16.0);
byte[] result = new byte[size * 16];
for (int i = 0; i < size; i++)
if ((i+1) * 16 > message.length)
//padding here????
else
byte[] block = Arrays.copyOfRange(message, i * 16, (i + 1) * 16);
byte[] encryptedBlock = encryptBlock(block);
System.arraycopy(encryptedBlock, 0, result, i*16, 16);
return result;
我如何填写这样的消息?
我不能使用零填充,因为每个字节都可能为零,并且它可能会影响带有尾随零的此类消息。
我找不到任何关于如何做到这一点的参考,甚至没有 here(描述 AES 加密的论文)
【问题讨论】:
【参考方案1】:填充有一个技巧:
你应该用填充长度的字节表示来填充:
333
或
4444
或 999999999
然后当你稍后读取第一个填充字节时,你就知道还有多少字节要读取。
【讨论】:
我如何知道消息是否被填充? 以后不要忘记接受(复选框)最有用的答案 你读取最后一个字节,如果有0,那么它没有被填充,或者类似的,否则你删除最后一个字节表示的字节数。但是想想 N-1 ür N +1。我现在不想去想。 好的,这就是我理解的方式,如果消息不需要填充,我应该添加一整块零,如果需要,我附加填充长度的字节表示 对不起,Alex,但是您对填充字节的表示还有很多不足之处,而且您的 cmets 似乎完全偏离了标准。【参考方案2】:您可以使用多种方法,从简单到高级。 Bruce Schneier 提出了两种相当简单的方法:
一个是用 n 个字节填充最后一个块,所有的值都是 n,这是 Alex Wien 建议的。这有问题(包括限制您使用长度小于 256 字节的块大小)。这种填充模式称为 PKCS#7 填充(用于 16 字节块)或 PKCS#5 填充(用于 8 字节块)。
另一种方法是附加一个值为 0x80 的字节(二进制值为 1000 0000 的字节),然后根据需要添加尽可能多的零字节来填充最后一个块。这种方法称为ISO padding,是ISO/IEC 9797-1 padding method 2的简称。padding本身就是bit-level padding,加一个值为1的bit,然后加0值的bit,直到到达block大小。
至于如何知道消息是否被填充,答案是消息将总是被填充:即使消息的最后一个块完全适合一个块(即message 是块大小的倍数),您必须添加一个虚拟的最后一个块。
如果您有兴趣研究一些更高级的方法,请在***上查找一种称为密文窃取的技术:http://en.wikipedia.org/wiki/Ciphertext_stealing
【讨论】:
以上是关于AES 应该使用啥样的填充?的主要内容,如果未能解决你的问题,请参考以下文章