BadPaddingException:由于java版本不同,给定最终块未正确填充

时间:2016-12-08 09:56:09

标签: java encryption aes badpaddingexception

我在客户端安装了java 8,我使用以下技术加密我的数据文件

    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    outputStream = new CipherOutputStream(new FileOutputStream(encryptedFile), cipher);

现在我在服务器端解密,我按照下面的代码安装了Java 7。

Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
inputStream = new CipherInputStream(new FileInputStream(encryptedFile), cipher);
outputStream = new FileOutputStream(decryptedFileName);

这样做会给我以下错误

Caused by: java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded
    at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:115) [jce.jar:1.7.0_71]
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:233) [jce.jar:1.7.0_71]
    at javax.crypto.CipherInputStream.read(CipherInputStream.java:209) [jce.jar:1.7.0_71]

当我在两侧安装相同的java版本(1.7)时,相同的代码工作正常。 我们如何解决这个问题,以便不改变任何一方的java版本

1 个答案:

答案 0 :(得分:0)

此问题可能有多种原因:

  1. 您没有指定获取/生成密钥的方式。如果您的JRE在拥有/不存在JCE Unlimited Strength Jurisdiction Policies方面有所不同,则一个将支持256位AES加密,另一个将仅支持128位。如果您根据可用的密钥长度生成密钥,则可能导致密钥不匹配。同时,两个Java 7环境可能都安装了相同的级别策略。

  2. 您没有在系统的任何一侧指定block cipher mode of operation或填充方案 - 我建议使用AEAD模式,例如GCMEAX或{{1} }(CTR + CBC-MAC)与CCM结合使用,但即使NoPaddingCBC/PKCS5Padding也优于默认CTR/NoPadding,只需调用{{1} }}。

  3. 您不能解释如何对密文进行编码,然后再将其保密,然后对其进行反序列化以进行解密。如果没有像十六进制或Base64这样的安全编码方案,您可能(阅读:最终会遇到)处理使用原始二进制值的编码问题。

  4. AES/ECB/PKCS5Padding更改为另一种操作模式后,您需要为加密和解密提供初始化向量(IV),并将密码与密文一起传输。 IV不需要以任何方式加密,但对于使用相同密钥加密的每条消息,它必须是唯一且不可预测的。因为它始终是密码的块大小(固定为16字节/ 128位AES),只需在密码文本前加上IV值,然后将其拆分以进行解密。

  5. AES(以及所有对称加密)使用相同的密钥进行加密和解密 - 不涉及 public private 密钥。它可能只是一个命名问题,但您尝试使用Cipher.getInstance("AES")解密的事实可能表明使用了错误的密钥。您应该验证加密和解密密钥是否都是字节相同的(相同长度(16,24或32字节)和相等)。 ECB"解密"将永远"成功"如果密文是块大小的精确倍数(16字节)。然后验证填充。如果您尝试使用错误的密钥解密消息,则通常会(255/256次)出现填充错误。另一种情况是最后一个字节解密为publicKey,这是PKCS#5 /#7的有效填充值,因此它不会检测填充错误。

  6. 演示ECB是Java 8(1.8.0_101)上的默认值:

    0x01