0

I need to get in Node js the same decrypted value that I get from my website in .NET C #

My code in the .NET C # class called Crypto is:

private static readonly string key = "Z8,omB0pxZwñ3h9s";

    public string Encrypt(string data)
    {
        string encData = null;
        byte[][] keys = GetHashKeys(key);

        try
        {
            encData = EncryptStringToBytes_Aes(data, keys[0], keys[1]);
            return encData;
        }
        catch (CryptographicException) {
            return null;
        }
        catch (ArgumentNullException) {
            return null;
        }
    }

    public string Decrypt(string data)
    {
        string decData = null;
        byte[][] keys = GetHashKeys(key);

        try
        {
            decData = DecryptStringFromBytes_Aes(data, keys[0], keys[1]);
        }
        catch (CryptographicException) { }
        catch (ArgumentNullException) { }

        return decData;
    }

    private byte[][] GetHashKeys(string key)
    {
        byte[][] result = new byte[2][];
        Encoding enc = Encoding.UTF8;

        SHA256 sha2 = new SHA256CryptoServiceProvider();

        byte[] rawKey = enc.GetBytes(key);
        byte[] rawIV = enc.GetBytes(key);

        byte[] hashKey = sha2.ComputeHash(rawKey);
        byte[] hashIV = sha2.ComputeHash(rawIV);

        Array.Resize(ref hashIV, 16);

        result[0] = hashKey;
        result[1] = hashIV;

        return result;
    }

    //source: https://msdn.microsoft.com/de-de/library/system.security.cryptography.aes(v=vs.110).aspx
    private static string EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
    {
        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("IV");

        byte[] encrypted;

        using (AesManaged aesAlg = new AesManaged())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt =
                        new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }
        return Convert.ToBase64String(encrypted);
    }

    //source: https://msdn.microsoft.com/de-de/library/system.security.cryptography.aes(v=vs.110).aspx
    private static string DecryptStringFromBytes_Aes(string cipherTextString, byte[] Key, byte[] IV)
    {
        byte[] cipherText = Convert.FromBase64String(cipherTextString);

        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText");
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");

        string plaintext = null;

        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = Key;
            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))
                    {
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }
        return plaintext;
    }

And what I have in Node js for now is this:

var sys = require ('sys'),
url = require('url'),
http = require('http'),
qs = require('querystring');
crypto = require('crypto-js');
var express = require('express');
var app = express();
var sql = require('mssql');
const getConn = require('./configVariables');

var config={
    server : getConn.getServer(),
    database : getConn.getDatabase(),
    user : getConn.getUser(),
    password : getConn.getPass(),
    port:getConn.getPort(),
    options: {
        encrypt: false
    }
};

http.createServer(function (req, res) {
    try{
        res.writeHead(200, {"Content-Type": "text/html;charset=UTF-8"});

        var key = "Z8,omB0pxZwñ3h9s";
        var secret = "ZZZZZZ";
        e1 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
        console.log("key: " + crypto.enc.Base64.stringify(e1.key));
        console.log("iv: " + crypto.enc.Base64.stringify(e1.iv));
        console.log("salt: " + crypto.enc.Base64.stringify(e1.salt));
        console.log("ciphertext: " + crypto.enc.Base64.stringify(e1.ciphertext));
        p = crypto.AES.decrypt(e1, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
        console.log("decrypted: " + crypto.enc.Utf8.stringify(p));        
        var isResponse = JSON.stringify({StatusCode:"200", info:"true", values:p})
        res.end(isResponse);
    }catch(err){
        var errorResponse = JSON.stringify({StatusCode:"400", Descripcion:"ERROR: " + err})
        res.end(errorResponse);
    }
}).listen(process.env.PORT);

If I encrypt in .NET the variable ZZZZZZ gives me the result I need. But in Node js while the result may be a bit similar, it is not the same as I get in .NET and I really need to have the exact same result for both encryption and decryption.

Please I need help. I do not manage at all in what is encryption

  • It's hard to follow crypto code on a phone. Have you stepped through and checked that the key and IV are the same on both ends? Generally people forget about the IV – Flydog57 Apr 10 '21 at 18:35
  • The truth @Flydog57 is that when debugging in C # the IV is an array of bytes that is obtained from obtaining the bytes of the Key. But in Node Js I can't do this same process so that IV is the same. I'm very lost, I don't know what to do. – Leonardo lagos catalán Apr 23 '21 at 22:48
  • Create an IV when you encrypt, and then send it in clear text to whomever is going to decrypt. They IV doesn't need to be protected - but it does need to be the same on both ends. You do need the key on both ends, but it needs to be protected. – Flydog57 Apr 23 '21 at 22:58

1 Answers1

0

The issue was not only because the IV was different. I provide more detail below:

In .NET C # the hashKey is a 32-byte array which comes from a 16-byte key string of text. But the hashIV is an array equivalent to the leading half of the array of the hashKey.

So in Node.js the algorithm to use is 'aes-256-cbc' assigning the keystring and IV variables the Buffer.from of bytes corresponding to each one, which must be the same as in C #.

Next I leave the Node.js solution that gave me the same result.

const crypto = require('crypto');
algorithm = "aes-256-cbc",
keystring = Buffer.from([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]),
iv = Buffer.from([ 1, 2, 3, 4, 5, ,6 ,7 ,8 9, 10, 11, 12, 13, 14, 15, 16]);
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;
}

var enc = Encrypt("ZZZZZZ");
console.log("enc: " + enc);
var dec = Decrypt(enc);
console.log("dec: " + dec);

The bytes specified in the answer are not really what was captured in C #, but I leave them as a sample.

If it works for someone, great.