Convert Node method to C#

I found this code to decrypt information using an AES key and a HASH code, but it is written in Node and I need to convert it to C# code:

result = (AESKEYBASE64:string,HMACKEYBASE64:string,encryptedValue:string):{error:boolean, info:string, value:string | null } => {
    try{
      const IV_SIZE = 16;
      const aesKey = Buffer.from(AESKEYBASE64, 'base64');
      const hmacKey = Buffer.from(HMACKEYBASE64, 'base64');
      const ivCipherTextHmac = Buffer.from(encryptedValue, 'base64');
      let algorithm = '';
      switch (aesKey.length) {
        case 16:
          algorithm = 'aes-128-cbc';
          break;
        case 32:
          algorithm = 'aes-256-cbc';
          break;
        default:
          algorithm = '';
      }
      const cipherTextLength = ivCipherTextHmac.length - hmacKey.length;
      const iv = ivCipherTextHmac.slice(0, IV_SIZE);
      const cipherText = ivCipherTextHmac.slice(IV_SIZE, cipherTextLength);
      const ivCipherText = Buffer.concat([iv, cipherText]);
      const receivedHMAC = ivCipherTextHmac.slice(cipherTextLength, ivCipherTextHmac.length);
      const calculatedHMAC = crypto.createHmac('sha256', hmacKey).update(ivCipherText).digest('base64');
      const bytes = Buffer.from(calculatedHMAC, 'base64');
      if (receivedHMAC.length === bytes.length) {
        const decipher = crypto.createDecipheriv(algorithm, aesKey, iv);
        const decrypted = decipher.update(cipherText);
        const final = Buffer.concat([decrypted, decipher.final()]);
        return { error: false, info: 'value ', value: final.toString('utf8') }
      }
      return { error: true, info: 'The signature is not valid', value: null }
    }catch(error:any){
      return { error: true, info: `Could not be deciphered->${encryptedValue}-> ${error.message}`, value: null }
    }
   
}

There are many Node methods that I cannot interpret in C#

>Solution :

To convert the provided Node.js code to C#, you can use the .NET Framework’s libraries for cryptographic operations. Here’s an equivalent C# implementation:

using System;
using System.Security.Cryptography;
using System.Text;

public class Decryptor
{
    public static (bool error, string info, string value) Decrypt(string aesKeyBase64, string hmacKeyBase64, string encryptedValueBase64)
    {
        try
        {
            int ivSize = 16;
            byte[] aesKey = Convert.FromBase64String(aesKeyBase64);
            byte[] hmacKey = Convert.FromBase64String(hmacKeyBase64);
            byte[] ivCipherTextHmac = Convert.FromBase64String(encryptedValueBase64);

            string algorithm = "";
            switch (aesKey.Length)
            {
                case 16:
                    algorithm = "AES-128-CBC";
                    break;
                case 32:
                    algorithm = "AES-256-CBC";
                    break;
            }

            if (string.IsNullOrEmpty(algorithm))
            {
                return (true, "Invalid AES key length", null);
            }

            int cipherTextLength = ivCipherTextHmac.Length - hmacKey.Length;
            byte[] iv = new byte[ivSize];
            Buffer.BlockCopy(ivCipherTextHmac, 0, iv, 0, ivSize);

            byte[] cipherText = new byte[cipherTextLength];
            Buffer.BlockCopy(ivCipherTextHmac, ivSize, cipherText, 0, cipherTextLength);

            byte[] receivedHMAC = new byte[hmacKey.Length];
            Buffer.BlockCopy(ivCipherTextHmac, cipherTextLength, receivedHMAC, 0, hmacKey.Length);

            HMACSHA256 hmac = new HMACSHA256(hmacKey);
            byte[] calculatedHMAC = hmac.ComputeHash(ivCipherTextHmac, 0, cipherTextLength);

            if (AreArraysEqual(receivedHMAC, calculatedHMAC))
            {
                using (Aes aesAlg = Aes.Create())
                {
                    aesAlg.Key = aesKey;
                    aesAlg.IV = iv;

                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                    using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        string decryptedValue = srDecrypt.ReadToEnd();
                        return (false, "Decryption successful", decryptedValue);
                    }
                }
            }

            return (true, "The signature is not valid", null);
        }
        catch (Exception ex)
        {
            return (true, $"Could not be deciphered -> {encryptedValueBase64} -> {ex.Message}", null);
        }
    }

    private static bool AreArraysEqual(byte[] a1, byte[] a2)
    {
        if (a1.Length != a2.Length)
        {
            return false;
        }

        for (int i = 0; i < a1.Length; i++)
        {
            if (a1[i] != a2[i])
            {
                return false;
            }
        }

        return true;
    }
}

This C# code should perform the same decryption and HMAC verification as the Node.js code you provided. Make sure to call the Decrypt method with your base64-encoded keys and encrypted value, and it will return the error status, info message, and decrypted value.

Leave a Reply