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.