BadPaddingException:由于java版本不同,给定的最后一个块没有正确填充
我在客户端安装了Java8,我正在使用下面的技术加密我的数据文件BadPaddingException:由于java版本不同,给定的最后一个块没有正确填充,java,encryption,aes,badpaddingexception,Java,Encryption,Aes,Badpaddingexception,我在客户端安装了Java8,我正在使用下面的技术加密我的数据文件 Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); outputStream = new CipherOutputStream(new FileOutputStream(encryptedFile), cipher); 现在我在服务器端解密,我已经按照下面的代码安装了Java7 Cipher c
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
outputStream = new CipherOutputStream(new FileOutputStream(encryptedFile), cipher);
现在我在服务器端解密,我已经按照下面的代码安装了Java7
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版本的情况下,任何一方都有可能导致此问题的原因:
GCM
、EAX
、或CCM
(CTR+CBC-MAC)以及NoPadding
,但是,即使是CBC/PKCS5Padding
或CTR/NoPadding
也比默认的AES/ECB/PKCS5Padding
要好,只需调用Cipher.getInstance(“AES”)
ECB
切换到另一种操作模式,您将需要为加密和解密提供初始化向量(IV),并将IV与密码文本一起传输。IV不需要以任何方式进行加密,但对于使用相同密钥加密的每条消息,它必须是唯一的且不可预测的。由于它始终是密码的块大小(AES固定为16字节/128位),只需在密文前面加上IV值,然后将其拆分以进行解密publicKey
解密的事实可能表明使用了错误的密钥。您应该验证加密密钥和解密密钥是否相同(长度相同(16、24或32字节)且相等)ECB
如果密码文本是块大小(16字节)的精确倍数,“解密”将始终“成功”。然后验证填充。如果试图用错误的密钥解密消息,通常(255/256次)会出现填充错误。另一种情况是最后一个字节解密为0x01
,这是PKCS#5/#7的有效填充值,因此它不会检测到填充错误AES/ECB/PKCS5Padding
是Java 8(1.8.0_101)上的默认值:
Post I/O代码可能重复。
@Test
public void testCipherGetInstanceShouldDefaultToECB() throws Exception {
// Arrange
final String PLAINTEXT = "This is a plaintext message."
final SecretKey key = new SecretKeySpec(Hex.decodeHex("0123456789ABCDEFFEDCBA9876543210" as char[]), "AES")
Cipher unspecified = Cipher.getInstance("AES")
final Cipher EXPECTED_CIPHER = Cipher.getInstance("AES/ECB/PKCS5Padding")
unspecified.init(Cipher.ENCRYPT_MODE, key)
EXPECTED_CIPHER.init(Cipher.DECRYPT_MODE, key)
// Act
byte[] cipherBytes = unspecified.doFinal(PLAINTEXT.getBytes(StandardCharsets.UTF_8))
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)}")
// Assert
byte[] recoveredBytes = EXPECTED_CIPHER.doFinal(cipherBytes)
String recovered = new String(recoveredBytes, StandardCharsets.UTF_8)
assert recovered == PLAINTEXT
}