I'm trying to implement following code from crypto-js in java for encryption
let toEncrypt= "my data";
cryptoJs.AES.encrypt(toEncrypt,"apasswordblabla").toString();
here is my implementation (AES/CBC/PKCS7Padding):
public String encrypt(Map<String,Object> param){
try {
String toEncrypt= objectMapper.writeValueAsString(param);
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] saltData = Arrays.copyOfRange(stringToEncrypt.getBytes(StandardCharsets.UTF_8), 8, 16);
final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, saltData, "apasswordblabla".getBytes(StandardCharsets.UTF_8), md5);
SecretKeySpec skeySpec = new SecretKeySpec(keyAndIV[0], "AES");
IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);
Cipher cipher;
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding",BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec,iv);
byte[] base64Encoded = Base64.getEncoder().encode(cipher.doFinal(toEncrypt.getBytes(StandardCharsets.UTF_8)));
return new String(base64Encoded);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException
| BadPaddingException | InvalidKeyException
| JsonProcessingException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
Implementation of generateIV(int ,int ,int ,byte[] , byte[], MessageDigest):
- This method is equivalent to OpenSSL's EVP_BytesToKey function, as I see in cryptojs source code ( [email protected] on file cipher-core.js line 658 ), the default formatter for AES is the OpenSSLFormatter
public static byte[][] generateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {
int digestLength = md.getDigestLength();
int requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength;
byte[] generatedData = new byte[requiredLength];
int generatedLength = 0;
try {
md.reset();
// Repeat process until sufficient data has been generated
while (generatedLength < keyLength + ivLength) {
// Digest data (last digest if available, password data, salt if available)
if (generatedLength > 0)
md.update(generatedData, generatedLength - digestLength, digestLength);
md.update(password);
if (salt != null)
md.update(salt, 0, 8);
md.digest(generatedData, generatedLength, digestLength);
// additional rounds
for (int i = 1; i < iterations; i++) {
md.update(generatedData, generatedLength, digestLength);
md.digest(generatedData, generatedLength, digestLength);
}
generatedLength += digestLength;
}
// Copy key and IV into separate byte arrays
byte[][] result = new byte[2][];
result[0] = Arrays.copyOfRange(generatedData, 0, keyLength);
if (ivLength > 0)
result[1] = Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);
return result;
} catch (DigestException e) {
throw new RuntimeException(e);
} finally {
// Clean out temporary data
Arrays.fill(generatedData, (byte)0);
}
}
and then I try to decrypt it Here using
let toDecrypt="[MY ENCRYPTED DATA IN BASE64]"
let decrypted = cryptoJs.AES.decrypt(toDecrypt, "apasswordblabla").toString(cryptoJs.enc.Utf8).toString();
console.log(decrypted);
And its always fail to decrypt, with error "Malformed utf-8 data". Hence, my java implementation is wrong
What did I got wrong here? or if there is any ready library to solve this issues please suggest