Secure Data: CryptoJS and Salesforce AMPScript Encryption and Decryption
This guide helps developers encrypt a given string or value using Salesforce AMPScript and decrypt it using the CryptoJS library on the frontend or backend.
The challenge is to get AMPscript in the Salesforce Platform to generate a cipher that CryptoJS can decrypt, considering many factors that affect the cipher, such as password, padding type, encryption mode, salt, IV, and the underlying encoding.
It's important to understand how the EncryptSymmetric
function encrypts the value internally; otherwise, you'll end up like me, trying to decrypt the value with different combinations.
Use Case: Secure Customer Data in Email Links
The simple use-case we can think of is to send an email from salesforce to a customer which has a clickable button that leads them to a user application. We want to pass a few query parameters in the button of the URL which helps retrieve the details of a customer. These parameters should not be in plaintext, and hence we decided to use AES CBC encryption on both sides.
On the Salesforce side, the AMPscript EncryptSymmetric
function is used to encrypt the values, and on the frontend side, the CryptoJS Decrypt
function is used.
AMPscript Encryption
Here is the structure of the EncryptSymmetric
function:
Encryption Algorithm - AES:CBC mode
Padding - pkcs7
Secret Key - 2Bx#16!4BJw10$bc
Salt - s3be6dcz83f2e6c4
IV - 3242782331362134424a773130246263
%%[
Set @encData=EncryptSymmetric('Arvind', /* String to encrypt */
'aes;padding=pkcs7', /* Encryption algorithm */
@null, /* Password external key */
'2Bx#16!4BJw10$bc', /* Password */
@null, /* Salt external key */
's3be6dcz83f2e6c4', /* Salt value */
@null, /* IV external key */
'3242782331362134424a773130246263' /* External key value */)
]%%
CryptoJS Decryption
And here is the equivalent function in CryptoJS that can decrypt the above.
const password = '2Bx#16!4BJw10$bc';
const salt = CryptoJS.enc.Hex.parse('s3be6dcz83f2e6c4');
const iv = CryptoJS.enc.Hex.parse(CryptoJS.enc.Utf8.parse('2Bx#16!4BJw10$bc').toString());
function encryptAES(valuetobeEncrypted) {
let encryptedStringHex = CryptoJS.AES.encrypt(valuetobeEncrypted, buildKey(password, salt), {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
return encryptedStringHex.toString()
}
/*decrypts string from salesforce*/
function decryptAES(valuetobeDecrypted) {
let decryptedStringHex = CryptoJS.AES.decrypt(
valuetobeDecrypted, buildKey(password, salt), {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return decryptedStringHex.toString(CryptoJS.enc.Utf8)
}
/*builds the key that matches the encryptsymmetric algorithm of salesforce AMPScript*/
function buildKey(password, salt) {
let key = CryptoJS.PBKDF2(password, salt, {
keySize: 256 / 32,
iterations: 1000,
hasher: CryptoJS.algo.SHA1
});
return key;
}
/*string to encrypt*/
let encrypted=encryptAES("Arvind")
console.log(`encrypted string is : ${encrypted}`)
console.log(`decrypted string is : ${decryptAES(encrypted)}`)
Here is a jsfiddle link for the same - JSFiddle Link
Additional Resources and References
Salesforce Stackexchange Link - Thanks to the answer from Cesar Amezcua which helped me with the solution.
Subscribe to my newsletter
Read articles from Arvind Kumar Thoppe directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Arvind Kumar Thoppe
Arvind Kumar Thoppe
Hey there! Thanks for visiting me :) I enjoy the process of writing code that enhances the experience of humans behind the pixels.More importantly, I like the tingle that this process bring along to my day :)