UPDATE: I made a standalone version (.class file with a main method) which works just fine on the new server. I can only think it has something to do with reading the passwords from the config file (I verified it's encoding, UTF-8, matches what the code expects). Could it be something to do with the newer OS (Win Server 2019 vs 2016)?
For the past couple of years I've been using this code to decrypt encrytped passwords at runtime. Recently, I needed to move the code (packaged in a .war file) to a new server. On the new server, decrypting throws the error, BadPaddingException: Given final block not properly padded.
I encrypt the passwords, base64 encode them, test decryption, then write them to a config file:
Original: encryptD3crypt
Encrypted: c05Nu2u8ck1tjad6vjeTgw==:74RyLEJEdTeeI23eaSjndw==
Decrypted: encryptD3crypt
The config file:
ldapUsername=svc-ldap ldapPassword=fCGJcn/kjzRZelXkygKTaw==:OOgOCHseTJjLeBhmkh3Vt46zK83HCz9s44OEIZwcofA=
The crypto code:
private static void createSecretKey(char[] password, byte[] salt, int iterationCount, int keyLength)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength);
SecretKey keyTmp = keyFactory.generateSecret(keySpec);
mKeySpec = new SecretKeySpec(keyTmp.getEncoded(), "AES");
}
public static String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
if (mKeySpec == null)
init();
Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
pbeCipher.init(Cipher.ENCRYPT_MODE, mKeySpec);
AlgorithmParameters parameters = pbeCipher.getParameters();
IvParameterSpec ivParameterSpec = parameters.getParameterSpec(IvParameterSpec.class);
//String cryptoText = new String(pbeCipher.doFinal(property.getBytes(Charset.forName("UTF-8"))));
byte[] cryptoText = pbeCipher.doFinal(property.getBytes("UTF-8"));
byte[] iv = ivParameterSpec.getIV();
return base64Encode(iv) + ":" + base64Encode(cryptoText);
}
public static String decrypt(String string) throws GeneralSecurityException, IOException {
if (mKeySpec == null)
init();
String iv = string.split(":")[0];
String property = string.split(":")[1];
Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
pbeCipher.init(Cipher.DECRYPT_MODE, mKeySpec, new IvParameterSpec(base64Decode(iv)));
return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
}
private static byte[] base64Decode(String property) throws IOException {
return Base64.getDecoder().decode(property);
}
private static String base64Encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
I've tried generating a new password which, again, works locally but fails on the new server. My encrypt/decrpyt ciphers are not mismatched. The old and new servers are using the same jdk.