javax.crypto.BadPaddingException Given final block not properly padded?
问题描述
最近在玩Cipher加密解密的时候,加密没错,但在解密是抛出错误:
出错描述:提供的字块不符合填补的,解密出错
出错原因:DES加密的时候,最后一位长度不足块长64时的,它会自动填补到64,那么在进行字节数组到字串的转化过程中,可以把它填补的不可见字符改变了,所以引发系统抛出异常(若是对称加密当加密与解密的密钥使用的不同,也会出现该异常)
问题处理
源代码(加密解密)
public static void encryptData(String plaintext) {
System.out.println("-------Encrypting data using AES algorithm-------");
try {
byte[] plaintTextByteArray = plaintext.getBytes("UTF8");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, getKey(strKey));
byte[] cipherText = cipher.doFinal(plaintTextByteArray);
System.out.println("Original data: " + plaintext);
System.out.println("Encrypted data:");
for (int i = 0; i < cipherText.length; i++) {
System.out.print(cipherText[i] + " ");
}
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(cipherText);
decryptData(encoded);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void decryptData(String cipherText) {
System.out.println();
System.out.println("-------Decrypting data using AES algorithm-------");
try {
BASE64Decoder decoder = new BASE64Decoder();
byte[] c = decoder.decodeBuffer(cipherText);
System.out.println("Encrypted data:" + cipherText);
Cipher cipher = Cipher.getInstance("AES");
Key key = setKey(strKey);
cipher.init(Cipher.DECRYPT_MODE, getKey(strKey));
byte[] bytes = cipher.doFinal(c);
System.out.println("Original data: " + new String(bytes));
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static Key getKey(String strKey) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
return new SecretKeySpec(enCodeFormat, "AES");
}
问题处理:
需要修改keyGenerator的init方法,指定SecurityRandom
private static Key getKey(String strKey) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
// 指定SecureRandom,使用指定的种子字节播种(需要保证两次调用的strKey不变)
keyGenerator.init(128 ,new SecureRandom(strKey.getBytes()));
// keyGenerator.init(128 ,new SecureRandom()); // 这样是不行的
SecretKey secretKey = keyGenerator.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
return new SecretKeySpec(enCodeFormat, "AES");
}
// 或者(一个道理)
private static Key getKey(String strKey) throws NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(strKey.getBytes());
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128 ,random);
SecretKey secretKey = keyGenerator.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
return new SecretKeySpec(enCodeFormat, "AES");
}