我正在制作一个程序,该程序可以通过 Socket 处理消息加密。但是,当我的消息中包含“o”、“b”或“c”和其他字母时,我会在解密时刻收到该异常。
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at teste1.Decrypt.decrypt(Decrypt.java:15)
at teste1.Server.main(Server.java:24)
是的,我的消息已包含所有字符,因此我不认为某些字符在传输过程中丢失。所以我真的不知道问题是什么,因为我尝试改变很多东西,但我继续收到这个异常。
解密类:
package teste1;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class Decrypt{
String IV = "AAAAAAAAAAAAAAAA";
public String decrypt(String str, String keys) throws Exception{
Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(keys.getBytes("UTF-8"), "AES");
decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(decrypt.doFinal(str.getBytes()),"UTF-8");
}
}
如果也想要加密类:
package teste1;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encrypt {
String IV = "AAAAAAAAAAAAAAAA";
public byte[] encrypt(String menE, String keys) throws Exception {
Cipher encrypt = Cipher.getInstance("AES/EBC/PKCS5Padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(keys.getBytes("UTF-8"), "AES");
encrypt.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
return encrypt.doFinal(menE.getBytes());
}
}
最佳答案
发生这种情况是因为字符串改变了你的字节,你真的应该使用 Base64 如果字符串是必须的。
如果您想测试运行此代码:
byte[] aByte = {-45};
System.out.println(Arrays.toString(new String(aByte, StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8)));
它将输出:[-17, -65, -67](不是 -45)。
无论如何,给你一些提示:
- 您无法使用“ECB”加密并使用“CBC”解密。
- 安 IV不应该是一个常数。您应该为每条消息生成一个新的 IV 并将其与消息一起发送。
- 不要指定
“UTF-8”
使用StandardCharsets.UTF_8
(请注意,如果使用android:StandardCharsets.UTF-8
是API 19+ 所以你应该有一个常量Charset.forName("UTF-8")
)
以下是一些有关如何使用 Base64 执行此操作的示例代码:
public byte[] encrypt(String message, String key, String iv) throws Exception {
Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
encrypt.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(Base64.getDecoder().decode(iv)));
return encrypt.doFinal(/*Get bytes from your message*/message.getBytes(StandardCharsets.UTF_8));
}
public String decrypt(String encryptedMessage, String key, String iv) throws Exception{
Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
decrypt.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(Base64.getDecoder().decode(iv)));
return new String(decrypt.doFinal(Base64.getDecoder().decode(encryptedMessage)), StandardCharsets.UTF_8);
}
并运行它
//your message
String message = "Hello World!";
//generate a new AES key. (an AES key is just a random sequence 16 bytes)
SecureRandom random = new SecureRandom();
byte[] aesKey = new byte[16];
random.nextBytes(aesKey);
//generate a new initialization vector (iv) which is also a random sequence of 16 bytes.
byte[] iv = new byte[16];
random.nextBytes(iv);
String aesKeyAsString = Base64.getEncoder().encodeToString(aesKey);
String ivAsString = Base64.getEncoder().encodeToString(iv);
//encrypt
byte[] encrypted = encrypt(message, aesKeyAsString, ivAsString);
//enocde your encrypted byte[] to String
String encryptedString = Base64.getEncoder().encodeToString(encrypted);
//decrypt
String decrypted = decrypt(encryptedString, aesKeyAsString, ivAsString);
//print your results
System.out.println("Encrypted: " + encryptedString + " Decrypted: " + decrypted);
输出:
加密:|加密字符串取决于生成的 key 和 iv|解密:世界你好!
您还可以使用更有效的方法,使用 byte[] 而不是字符串,但这是您的选择。
关于java - BadPaddingException 仅包含 "o"、 "b"、 "c"等字母,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55384527/