Java中的AES算法,加密恰好一个block的时候返回两个block,为什么?

输入长度小于一个block的时候输出一个block,这没问题,因为做了padding
但为什么输入恰好是一个block(16 bytes)的时候,输出变为2个block(32 bytes),简直无法理解啊

javapublic static void main(final String[] args) throws Exception {
    final byte[] keyBytes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
    final SecretKey key = new SecretKeySpec(keyBytes, "AES");
    final Cipher aes = Cipher.getInstance("AES");
    aes.init(Cipher.ENCRYPT_MODE, key);
    final byte[] input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
    final byte[] result = aes.doFinal(input);
    System.out.println(result.length); // prints 32
    return;
}
阅读 4.4k
1 个回答

你在getInstance时没有指定padding算法,默认采用的是PKCS5Padding
这种padding模式下,如果末位分组缺少n个字节,就补足nn

If numberOfBytes(clearText) mod 16 == 15, PM = M + 0x01
If numberOfBytes(clearText) mod 16 == 14, PM = M + 0x0202
If numberOfBytes(clearText) mod 16 == 13, PM = M + 0x030303
...
If numberOfBytes(clearText) mod 16 == 1, PM = M + (0x0F0F0F...0F0F)
                                                   |---15个0x0F---|

你可能会想,对啊没错啊,如果正好长度是16,不就不用补码了么:

If numberOfBytes(clearText) mod 16 == 0, PM = M + (nothing...)

那么问题来了,我在进行逆操作,比如解密的时候,对于一个已经padding过的末位分组,末尾是 0x0202, 我怎么恢复它padding之前的样子呢?因为可能会有两种情况

  1. 未padding之前就是16字节0x0202结尾
  2. 它本来是14个字节 ,padding之后变成14个字节+ 0x0202 = 16个字节

所以,实际上,如果末尾分组的长度正好等于一个分组长度的话,还需要再补nn,也就是

If numberOfBytes(clearText) mod 16 == 0, PM = M + (0x101010...1010)
                                                   |---16个0x10---|
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题