Java 使用AES算法解密消息时异常:给定的最终块未正确填充

Java 使用AES算法解密消息时异常:给定的最终块未正确填充,java,encryption,Java,Encryption,我想用AES算法进行解密 我的代码如下: public static String decrypt(String key, byte[] encrypted) throws GeneralSecurityException { byte[] raw = key.getBytes(Charset.forName("US-ASCII")); if (raw.length != 16) { throw new Illeg

我想用AES算法进行解密 我的代码如下:

public static String decrypt(String key, byte[] encrypted)
            throws GeneralSecurityException {

        byte[] raw = key.getBytes(Charset.forName("US-ASCII"));
        if (raw.length != 16) {
            throw new IllegalArgumentException("Invalid key size.");
        }
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec,new IvParameterSpec(new byte[16]));
        byte[] original = cipher.doFinal(encrypted);

        return new String(original, Charset.forName("US-ASCII"));
    }

为什么我会得到这个例外

AES是一种分组密码,以16字节的块进行加密。填充用于填充消息,使其大小为16字节的倍数PKCS-5填充将缺少的字节数确定为16的倍数,然后写入此数字,直到填充充分为止

这样的信息(十六进制):

会像这样被填充

D1 F2 05 7E 97 54 27 89 F2 07 07 07 07 07 07 07 
                           --------------------  pad
解密消息时,将检查填充是否正确。如果没有,那就是出了问题

典型原因: 通常,当填充错误时,整个解密都会出错。在解密中使用NOP只能消除症状,而不能解决问题

以下所有情况都可能触发填充异常:

  • 解密时使用错误的IV
  • 解密时使用错误的密钥
  • 解密时使用错误的链接模式(CBC)
  • 或使用错误的填充模式(!)

您确定加密程序使用了全零IV吗?这通常是不好的做法;除非密钥总是唯一的,否则每个密钥的IVs必须是唯一的且不可预测的,通常通过使其随机来实现,并且必须与密文一起发送并在解密时使用。PKCS5填充数据上的对称解密错误大约99.6%被捕获为“错误填充”,其余部分为随机垃圾数据。@dave_thompson_085:如果我使用AES/CBC/NoPadding,则不会发生此类异常是的,如果您告诉它不要检查填充,则即使存在填充或解密错误,也找不到填充或解密错误。如果使用NoPadding进行解密,您会得到正确的数据吗?尤其是长度至少为17字节的数据?如果没有,那么正如@Ebbe所说,模式、键或IV都是错误的。在这三个人中,你的零IV在我看来是最可疑的。很好的解释!!有帮助
D1 F2 05 7E 97 54 27 89 F2 07 07 07 07 07 07 07 
                           --------------------  pad