Reputation: 71
currently I need to create a hash that needs to be compaired in Mulesoft from a javascript file, the current way is using directly Crypto.SHA1 method but it's obsolete and now mule application is using SHA256 but I cannot figureout how to create the same flow to execute the encryption from Javascript.
This is an example shared by other user in stackoverflow to implement MD5 encryption in Javascript:
var password = CryptoJS.enc.Utf8.parse("test");
var salt = CryptoJS.enc.Hex.parse("2121F055C39F5A75");
var iterations = 31;
// PBE according to PKCS#5 v1.5 (in other words: PBKDF1)
var md5 = CryptoJS.algo.HMAC256.create();
md5.update(password);
md5.update(salt);
var result = md5.finalize();
md5.reset();
for(var i = 1; i < iterations; i++) {
md5.update(result);
result = md5.finalize();
md5.reset();
}
// splitting key and IV
var key = CryptoJS.lib.WordArray.create(result.words.slice(0, 2));
var iv = CryptoJS.lib.WordArray.create(result.words.slice(2, 4));
var encrypted = CryptoJS.DES.encrypt("test", key, {
iv: iv
});
enc.innerHTML = encrypted.ciphertext.toString(); // HEX
https://jsfiddle.net/artjomb/Lpbo7yrb/
Upvotes: 1
Views: 730
Reputation: 49415
The posted code applies PBEWithMD5andDES, which works differently than PBEWithHmacSHA256AndAES_256, and therefore unfortunately cannot be used.
PBEWithHmacSHA256AndAES_256 applies PBKDF2 for deriving a 256 bits key and AES with CBC and PKCS#7 padding for encryption. A possible implementation with CryptoJS is:
var passphrase = "My Passphrase";
var saltWA = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f"); // static only for test!
var ivWA = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f"); // static only for test!
var iterations = 10000;
var plaintext = "The quick brown fox jumps over the lazy dog";
var keyWA = CryptoJS.PBKDF2(
passphrase, saltWA, {keySize: 256/32, iterations: iterations, hasher: CryptoJS.algo.SHA256});
var ciphertextCP = CryptoJS.AES.encrypt(plaintext, keyWA, {iv: ivWA}); // applies CBC and PKCS#7 by default
var ciphertextHex = ciphertextCP.ciphertext.toString();
ct.innerHTML = ciphertextHex; // a08af68882ef646631c510b0742272308eca57bd251f962444a01abcecf41bfc804b5e3e9f666f125103d1954809edd5
var decrypted = CryptoJS.AES.decrypt(ciphertextCP, keyWA, {iv: ivWA});
pt.innerHTML = decrypted.toString(CryptoJS.enc.Utf8); // The quick brown fox jumps over the lazy dog
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<div id="ct"></div>
<div id="pt"></div>
which gives the hex encoded ciphertext:
a08af68882ef646631c510b0742272308eca57bd251f962444a01abcecf41bfc804b5e3e9f666f125103d1954809edd5
Beware: For comparison with the reference value of the Java code below, a static IV and salt are used. In practice, however, salt and IV must be randomly generated for each ciphertext for security reasons. Since salt and IV are needed for decryption and are not secret, they are passed to the decrypting side along with the ciphertext, typically concatenated, e.g. salt|IV|ciphertext.
For a test of the CryptoJS implementation, a reference value is needed. The following code is an encryption with PBEWithHmacSHA256AndAES_256 in Java:
import java.nio.charset.StandardCharsets;
import java.util.HexFormat;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
...
String password = "My Passphrase" ;
byte[] salt = HexFormat.of().parseHex("000102030405060708090a0b0c0d0e0f"); // static only for test
byte[] iv = HexFormat.of().parseHex("101112131415161718191a1b1c1d1e1f"); // static only for test
int iterations = 10000 ;
String plaintext = "The quick brown fox jumps over the lazy dog";
IvParameterSpec ivSpec = new IvParameterSpec(iv);
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations, ivSpec);
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256");
SecretKey secretKey = kf.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
byte[] decryptedtext = cipher.doFinal(ciphertext);
System.out.println(HexFormat.of().formatHex(ciphertext)); // a08af68882ef646631c510b0742272308eca57bd251f962444a01abcecf41bfc804b5e3e9f666f125103d1954809edd5
System.out.println(new String(decryptedtext, StandardCharsets.UTF_8)); // The quick brown fox jumps over the lazy dog
The ciphertext corresponds to that of the CryptoJS implementation which proves that the CryptoJS code is indeed functionally identical to PBEWithHmacSHA256AndAES_256.
Upvotes: 2