Search code examples
javascriptc#node.jsaescryptojs

AES encryption in Node JS and C# gives different results


I have a use case where the text has to be encoded and sent using the AES 256 algorithm. The client-side code is in C# which would be decrypting the code.

Encryption code in JS:

const crypto = require('crypto');
  algorithm = 'aes-256-cbc',
  secret = '1234567890123456',
  keystring = crypto.createHash('sha256').update(String(secret)).digest('base64').substr(0, 16);
  iv = crypto.createHash('sha256').update(String(secret)).digest('base64').substr(0, 16);
  inputEncoding = 'utf8',
  outputEncoding = 'base64';


function encrypt(text) {
  let cipher = crypto.createCipheriv('aes-256-cbc', keystring, iv);
  let encrypted = cipher.update(text, inputEncoding, outputEncoding)
  encrypted += cipher.final(outputEncoding);
  return encrypted;
}

Updated code used in the client side:

var keybytes = Encoding.UTF8.GetBytes(passwordKey);
var iv = Encoding.UTF8.GetBytes(passwordKey);

private byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv)
        {
            try
            {
                // Check arguments.  
                if (plainText == null || plainText.Length <= 0)
                {
                    throw new ArgumentNullException("plainText");
                }
                if (key == null || key.Length <= 0)
                {
                    throw new ArgumentNullException("key");
                }
                if (iv == null || iv.Length <= 0)
                {
                    throw new ArgumentNullException("key");
                }
                byte[] encrypted;
                // Create a RijndaelManaged object  
                // with the specified key and IV.  
                using (var rijAlg = new RijndaelManaged())
                {
                    rijAlg.Mode = CipherMode.CBC;
                    rijAlg.Padding = PaddingMode.PKCS7;
                    rijAlg.FeedbackSize = 128;

                    rijAlg.Key = key;
                    rijAlg.IV = iv;

                    // Create a decrytor to perform the stream transform.  
                    var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

                    // Create the streams used for encryption.  
                    using (var msEncrypt = new MemoryStream())
                    {
                        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                        {
                            using (var swEncrypt = new StreamWriter(csEncrypt))
                            {
                                //Write all data to the stream.  
                                swEncrypt.Write(plainText);
                            }
                            encrypted = msEncrypt.ToArray();
                        }
                    }
                }
                // Return the encrypted bytes from the memory stream.  
                return encrypted;
            }
            catch (Exception ex)
            {
                throw ex;
                //LoggerCS.logError("Utility", "EncryptStringToBytes", JsonConvert.SerializeObject(null), ex.ToString(), ex.StackTrace);
            }
            return null;
        }

The keyString and IV value used are same in C# and is encrypted using Utf8. Looking for the equivalent operation in Node JS.


Solution

  • The resolution was pretty simple than expected. The RijndaelManaged code with keylen 128 referred to AES-128 algorithm and using aes-128-cbc in nodeJS.

    Also, since the C# code used getBytes for key and iv value. Buffer.from(secret) had to be used for both key and iv value in nodeJS. Final solution looks like:

       const crypto = require('crypto');
          algorithm = "aes-128-cbc",
          secret = '1234567890123456',
          keystring = new Buffer(secret),
          iv = new Buffer(secret),
          inputEncoding = 'utf8',
          outputEncoding = 'base64';
        function encrypt(text) {
          let cipher = crypto.createCipheriv(algorithm,keystring, iv);
          let encrypted = cipher.update(text, inputEncoding, outputEncoding)
          encrypted += cipher.final(outputEncoding);
          return encrypted;
        }
        
        function decrypt(encrypted) {
          let decipher = crypto.createDecipheriv(algorithm,keystring, iv)
          let dec = decipher.update(encrypted, outputEncoding, inputEncoding)
          dec += decipher.final(inputEncoding);
          return dec;
        }