AES应该使用哪种填充?

时间:2012-11-26 20:04:33

标签: java cryptography aes block padding

我已经实现了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加密的文章)

2 个答案:

答案 0 :(得分:6)

您可以使用多种方法,从简单到高级。 Bruce Schneier提出了两种相当简单的方法:

一个是用n个字节填充最后一个块,所有值都是n,这就是Alex Wien所建议的。这有问题(包括限制您长度小于256字节的块大小)。这种填充模式称为PKCS#7填充(用于16字节块)或PKCS#5填充(用于8字节块)。

另一个是附加一个值为0x80的字节(一个字节值为二进制值为1000 0000),后跟填充最后一个块所需的零字节数。此方法称为ISO填充,它是ISO / IEC 9797-1填充方法2的缩写。填充本身是位级填充,添加单个值1,然后添加0值位,直到到达块大小

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

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

答案 1 :(得分:0)

有一个填充技巧:

你应该使用填充长度的字节重新填充:

333

4444

或999999999

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