Search code examples
encryptionpostmanaescryptojs

How to implement AES 128 in Crypto JS for postman


I have this c# code:

    public string Encrypt( string aesKey)
    {            
        var data = "ASD_POC";
        var aesKey = "OxLDVPTHLk5EHR5AE8O0rg==";            
        var token = Encoding.UTF8.GetBytes(data);
        byte[] _key = Convert.FromBase64String(aesKey);
        string retnResult = string.Empty;
        AesCryptoServiceProvider aesProvider = new System.Security.Cryptography.AesCryptoServiceProvider();
        MemoryStream memStream = null;
        CryptoStream cryptoStream = null;
        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        byte[] cipherText;

        try
        {
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            aesProvider.BlockSize = 128;
            aesProvider.KeySize = 128;
            aesProvider.GenerateIV();
            memStream = new MemoryStream();
            cryptoStream = new CryptoStream(memStream, aesProvider.CreateEncryptor(_key, aesProvider.IV), CryptoStreamMode.Write);
            cryptoStream.Write(token, 0, token.Length);
            cryptoStream.FlushFinalBlock();
            cipherText = memStream.ToArray();
            var combinedIvCipherText = new byte[aesProvider.IV.Length + cipherText.Length];
            Array.Copy(aesProvider.IV, 0, combinedIvCipherText, 0, aesProvider.IV.Length);
            Array.Copy(cipherText, 0, combinedIvCipherText, aesProvider.IV.Length, cipherText.Length);
            retnResult = Convert.ToBase64String(combinedIvCipherText);
        }

I have tried to implement this for the Postman collection:

var CryptoJS = require("crypto-js");
// Generate random 16 bytes to use as IV
var IV = CryptoJS.lib.WordArray.random(16);

var data = "ASD_POC";
var aesKey = "OxLDVPTHLk5EHR5AE8O0rg=="; 

var tokenData = atob(aesKey);
var Key = Uint8Array.from(tokenData, b => b.charCodeAt(0));

function encrypt(data) {
    var val = CryptoJS.enc.Utf8.parse(data);
    var encrypted = CryptoJS.AES.encrypt(
        val, 
        Key, 
        { 
            iv: IV,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
            keySize: 128,
            BlockSize: 128
        }).toString();
        console.log(encrypted);
    var b64 = CryptoJS.enc.Base64.parse(encrypted).toString(CryptoJS.enc.Hex);
    
    console.log(b64)    
    return b64;
}

But when I'm trying to string from CryptoJs - I got an error that I can't. What I'm doing wrong in my implementation? I tried to google a little bit more info about CryptoJs - but couldn't found anything more than and it does not contain a lot of information.


Solution

  • The CryptoJS code lacks concatenation of IV and ciphertext.

    In addition, wrong encodings are used in some cases. CryptoJS works with WordArrays and provides different encoders for the conversion to this type.

    A possible implementation with CryptoJS is:

    var data = "ASD_POC";
    var aesKey = "OxLDVPTHLk5EHR5AE8O0rg=="; 
    var ivWA = CryptoJS.lib.WordArray.random(16);
    //var ivWA = CryptoJS.enc.Hex.parse("2423c5414ead3812e68a799c8c6deab7"); //for testing only
    function encrypt(data, aesKey) {
        var dataWA = CryptoJS.enc.Utf8.parse(data);
        var keyWA = CryptoJS.enc.Base64.parse(aesKey);
        var ciphertext = CryptoJS.AES.encrypt(dataWA, keyWA, {iv: ivWA}).ciphertext;
        var ivCiphertext = ivWA.clone().concat(ciphertext);
        var ivCiphertextB64 = ivCiphertext.toString(CryptoJS.enc.Base64);
        return ivCiphertextB64;
    }
    
    document.getElementById("ct").innerHTML = encrypt(data, aesKey); 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
    <p style="font-family:'Courier New', monospace;" id="ct"></p>

    As test, a ciphertext can be created with the C# code, e.g. JCPFQU6tOBLminmcjG3qt+JeEXrh5/9x+QSc7Emc6cQ=. The first 16 bytes are the IV, which is hex encoded 2423c5414ead3812e68a799c8c6deab7. If this IV is used in the CryptoJS code (s. commented out line), the same ciphertext results.