6

我已经实现了 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;
}

我怎样才能填充这样的消息?

我不能使用零填充,因为每个字节都可能为零,并且它可能会影响带有尾随零的此类消息。

我找不到任何关于如何做到这一点的参考资料描述 AES 加密的论文)

4

2 回答 2

12

您可以使用多种方法,从简单到高级。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尺寸。

至于如何知道消息是否被填充,答案是消息总是会被填充:即使消息的最后一个块完全适合一个块(即消息的大小是块大小的倍数),你将不得不添加一个虚拟的最后一个块。

如果您有兴趣研究一些更高级的方法,请在维基百科上查找一种称为密文窃取的技术:http ://en.wikipedia.org/wiki/Ciphertext_stealing

于 2012-11-26T20:38:10.420 回答
0

填充有一个技巧:

您应该使用填充长度的字节表示来填充:

333

或者

4444

或 999999999

然后当您稍后读取第一个填充字节时,您知道还有多少字节要读取。

于 2012-11-26T20:06:23.683 回答