我在客户端安装了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版本
答案 0 :(得分:0)
此问题可能有多种原因:
您没有指定获取/生成密钥的方式。如果您的JRE在拥有/不存在JCE Unlimited Strength Jurisdiction Policies方面有所不同,则一个将支持256位AES加密,另一个将仅支持128位。如果您根据可用的密钥长度生成密钥,则可能导致密钥不匹配。同时,两个Java 7环境可能都安装了相同的级别策略。
您没有在系统的任何一侧指定block cipher mode of operation或填充方案 - 我建议使用AEAD模式,例如GCM
,EAX
或{{1} }(CTR + CBC-MAC)与CCM
结合使用,但即使NoPadding
或CBC/PKCS5Padding
也优于默认CTR/NoPadding
,只需调用{{1} }}。
您不能解释如何对密文进行编码,然后再将其保密,然后对其进行反序列化以进行解密。如果没有像十六进制或Base64这样的安全编码方案,您可能(阅读:最终会遇到)处理使用原始二进制值的编码问题。
从AES/ECB/PKCS5Padding
更改为另一种操作模式后,您需要为加密和解密提供初始化向量(IV),并将密码与密文一起传输。 IV不需要以任何方式加密,但对于使用相同密钥加密的每条消息,它必须是唯一且不可预测的。因为它始终是密码的块大小(固定为16字节/ 128位AES),只需在密码文本前加上IV值,然后将其拆分以进行解密。
AES(以及所有对称加密)使用相同的密钥进行加密和解密 - 不涉及 public 和 private 密钥。它可能只是一个命名问题,但您尝试使用Cipher.getInstance("AES")
解密的事实可能表明使用了错误的密钥。您应该验证加密和解密密钥是否都是字节相同的(相同长度(16,24或32字节)和相等)。 ECB
"解密"将永远"成功"如果密文是块大小的精确倍数(16字节)。然后验证填充。如果您尝试使用错误的密钥解密消息,则通常会(255/256次)出现填充错误。另一种情况是最后一个字节解密为publicKey
,这是PKCS#5 /#7的有效填充值,因此它不会检测填充错误。
演示ECB
是Java 8(1.8.0_101)上的默认值:
0x01