Search code examples
node.jsvb.netencryptionaescryptojs

Encrypt string using vb.net AES/CBC and need to decrypt using JavaScript CryptoJS


I have a vb.net Windows form app that encrypts a string to a file. I now need JavaScript to decrypt that value. I have attempted to use CryptoJS but I am struggling with syntax and how to get the passphrase, salt and init vector in the right format to use in CryptoJS.PBKDF2 (assuming that is the right thing to use).

Calling Method

Dim encryptedComplianceValue = encrypt2(complianceValue, "Password", "Salt Value", "SHA1", 2, "@1B2c3D4e5F6g7H8", 256)

Encryption Method

Public Function encrypt2(ByVal plainText As String, ByVal passPhrase As String, ByVal saltValue As String, ByVal hashAlgorithm As String, ByVal passwordIterations As Integer, ByVal initVector As String, ByVal keySize As Integer) As String

    Dim initVectorBytes As Byte()
    initVectorBytes = Encoding.ASCII.GetBytes(initVector)

    Dim saltValueBytes As Byte()
    saltValueBytes = Encoding.ASCII.GetBytes(saltValue)

    Dim plainTextBytes As Byte()
    plainTextBytes = Encoding.UTF8.GetBytes(plainText)

    Dim password As Rfc2898DeriveBytes
    password = New Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations)

    Dim keyBytes As Byte()
    keyBytes = password.GetBytes(keySize / 8)

    Dim symmetricKey As RijndaelManaged
    symmetricKey = New RijndaelManaged()

    symmetricKey.Mode = CipherMode.CBC

    Dim encryptor As ICryptoTransform
    encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)

    Dim memoryStream As MemoryStream
    memoryStream = New MemoryStream()

    Dim cryptoStream As CryptoStream
    cryptoStream = New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
    cryptoStream.FlushFinalBlock()

    Dim cipherTextBytes As Byte()
    cipherTextBytes = memoryStream.ToArray()

    memoryStream.Close()
    cryptoStream.Close()

    Dim cipherText As String
    cipherText = Convert.ToBase64String(cipherTextBytes)

    Return cipherText
End Function

JavaScript

function decryptMsg256() 
{
    var keySize = 256;
    var iterations = 2;
    var algorithm = 'AES-256-CBC';

    // the password that user provides
    var userPass = "Password"; 
    console.log("user pass : " + userPass);

    // get the encrypted msg 
    var encMsg64 = "v6shkblimfQMOoa8VxICjQ==";
    var encMsg = CryptoJS.enc.Base64.parse(encMsg64);



    //var salt =CryptoJS.enc.Utf8.parse("Mon,07-Mar-2016 18:50:46 GMT");
    var salt = "Salt Value";
    console.log('salt:  '+ salt);
    var saltbytes = [];

    for (var i = 0; i <salt.length; ++i) {
        saltbytes .push(salt.charCodeAt(i));
    }
    console.log('saltbytes:  '+ saltbytes );

    //var iv =CryptoJS.enc.Utf8.parse("@1B2c3D4e5F6g7H8");
    var iv = "@1B2c3D4e5F6g7H8";
    console.log('IV:  '+ iv);
    var ivbytes = [];

    for (var i = 0; i <iv.length; ++i) {
        ivbytes.push(iv.charCodeAt(i));
    }
    console.log('ivbytes:  '+ ivbytes );

    //var saltBuffer = new Buffer(salt);
    //var passwordBuffer = new Buffer(userPass);

    var key = CryptoJS.PBKDF2(userPass, saltbytes,{keyBytes: 32,      iterations: 2 });
    //var key = CryptoJS.PBKDF2(userPass, salt, iterations, keySize/8);
    //var decipher = CryptoJS.createDecipheriv(algorithm, key, iv);

    console.log( 'key: '+ key);
    var keybytes = [];

    for (var i = 0; i <key.length; ++i) {
        keybytes.push(key.charCodeAt(i));
    }
    console.log('keybytes:  '+ keybytes);


    //var plainText="Hello, World!";

    //console.log('Plain Text  '+ plainText );

    //var encMsg = CryptoJS.AES.encrypt(plainText, key,  {
         //               iv:iv,
          //            mode: CryptoJS.mode.CBC,
           //             padding: CryptoJS.pad.Pkcs7
    //      });


    //console.log('Encrypted Message  '+ encMsg );




    var decText = '';

    var decMsg = CryptoJS.AES.decrypt( encMsg, key, {
                    iv:iv,
                    mode: CryptoJS.mode.CBC,
                    //padding: CryptoJS.pad.Pkcs7
                    } );
    //console.log( "decryptedData = " + decMsg );

    // convert to UTF8 string
    decText = decMsg.toString( CryptoJS.enc.Utf8);
    console.log( "decryptedText = " + decText );

}

Solution

  • You have multiple issues:

    • Your IV is a simple ASCII string, so you can easily parse it to a binary format with

      var iv = CryptoJS.enc.Utf8.parse("@1B2c3D4e5F6g7H8");
      
    • Don't use your custom "binary" format with saltbytes.push(salt.charCodeAt(i)); or similar. You need to use CryptoJS' native format, which is available through

      CryptoJS.enc.<Encoder>.parse(string)
      
    • The output size of PBKDF2 is specified with keySize and not keyBytes:

      var key = CryptoJS.PBKDF2(userPass, salt, {keySize: 256/32,      iterations: 2 });
      
    • The decryption function expects the ciphertext to be a CipherParams object. Good thing, duck-typing works:

      var decMsg = CryptoJS.AES.decrypt({
          ciphertext: encMsg
      }, key, {
          iv: iv
      });