如何从 DecryptStringFromBytes_Aes 获得与我在 .NET C# 中但在 Node js 中相同的结果?

问题描述

我需要在 Node js 中获得与我在 .NET C# 中从我的网站获得的相同解密值

我在名为 Crypto 的 .NET C# 类中的代码是:

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[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[] 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;
    }

我现在在 Node js 中拥有的是:

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,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);

如果我在 .NET 中加密,变量 ZZZZZZ 会给我我需要的结果。 但是在 Node js 中虽然结果可能有点相似,但它与我在 .NET 中得到的结果不同,我确实需要对加密和解密都具有完全相同的结果。

请我需要帮助。我根本不管理什么是加密

解决方法

问题不仅仅是因为 IV 不同。我在下面提供了更多详细信息:

在 .NET C# 中,hashKey 是一个 32 字节的数组,它来自一个 16 字节的文本键字符串。但是 hashIV 是一个数组,相当于 hashKey 数组的前半部分。

因此,在 Node.js 中,使用的算法是“aes-256-cbc”,为 keystring 和 IV 变量分配对应于每个字节的 Buffer.from,这必须与 C# 中的相同。

接下来,我放弃了给我相同结果的 Node.js 解决方案。

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,8 9,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,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);

答案中指定的字节实际上并不是在 C# 中捕获的,但我将它们留作示例。

如果对某人有用,那就太好了。