我一直在try 通过AES和C#以可互操作的方式对中的字符串进行加密和解密.我的客户机应用程序是一个 node 服务器,它与dot-NET中供应商的API进行通信.

供应商使用以下方法加密和解密字符串:

public static string Encrypt(string data, string key)
{
  string IV = key.Substring(0, 16);
  byte[] iv = Encoding.UTF8.GetBytes(IV);
  byte[] array;
  using(Aes aes = Aes.Create())
  {
    aes.Key = Encoding.UTF8.GetBytes(key);
    aes.IV = iv;
    ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
    using(MemoryStream memoryStream = new MemoryStream())
    {
      using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
      {
        using(StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
        {
          streamWriter.Write(data);
        }
        array = memoryStream.ToArray();
      }
    }
  }
  return Convert.ToBase64String(array);
}



public static string Decrypt(string data, string key)
{
  string IV = key.Substring(0, 16);
  byte[] iv = Encoding.UTF8.GetBytes(IV);
  byte[] buffer = Convert.FromBase64String(data);
  using(Aes aes = Aes.Create())
  {
    aes.Key = Encoding.UTF8.GetBytes(key);
    aes.IV = iv;
    ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
    using(MemoryStream memoryStream = new MemoryStream(buffer))
    {
      using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
      {
        using(StreamReader streamReader = new StreamReader((Stream)cryptoStream))
        {
          return streamReader.ReadToEnd();
        }
      }
    }
  }
}

例如,我try 了crypto-js来解密字符串,但我无法使其工作:

const encryptedText = CryptoJS.enc.Base64.parse(base64Value)
const encrypted2 = encryptedText.toString(CryptoJS.enc.Base64);
const decrypt2 = CryptoJS.AES.decrypt(encrypted2, key, {
 mode: CryptoJS.mode.ECB,
 padding: CryptoJS.pad.Pkcs7
});

console.log(decrypt2.toString(CryptoJS.enc.Utf8)) // (also tried various other encodings, Utf16, Utf16LE and others)

推荐答案

以下 node .js代码应该可以正确地与您的.NET代码.

我们使用算法aes-256-cbc来匹配C#示例中使用的模式.

const crypto = require("crypto");
const 算法rithm = "aes-256-cbc";

function encrypt(plainText, key, iv, outputEncoding = "base64") {
    const cipher = crypto.createCipheriv(算法rithm, key, iv);
    const output = Buffer.concat([cipher.update(plainText), cipher.final()]).toString(outputEncoding);
    return output.replace('+', '-').replace('/', '_').replace('=', '');
}

function decrypt(cipherText, key, iv, outputEncoding = "utf8") {
    cipherText = Buffer.from(cipherText, "base64");
    const cipher = crypto.createDecipheriv(算法rithm, key, iv);
    return Buffer.concat([cipher.update(cipherText), cipher.final()]).toString(outputEncoding);
}

const KEY = 'KFmnMAPzP!g@6Dy5HD?JSgYC9obE&m@m';
const IV = KEY.slice(0,16);

// Taking the output from our C# sample...
const encrypted = 'SORoNS48u0KniiANU3Y9Mw==';
console.log("Encrypted (base64):", encrypted);
const decrypted = decrypt(encrypted, KEY, IV)
console.log("Decrypted:", decrypted);

等效的C代码如下:

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
                    
public class Program
{
    public static void Main()
    {
        var str = Encrypt("test", "KFmnMAPzP!g@6Dy5HD?JSgYC9obE&m@m");
        Console.WriteLine("Encrypted: " + str);
        Console.WriteLine("Decrypted: " + Decrypt(str, "KFmnMAPzP!g@6Dy5HD?JSgYC9obE&m@m"));
    }
    
    public static string Encrypt(string data, string key)
    {
      string IV = key.Substring(0, 16);
      byte[] iv = Encoding.UTF8.GetBytes(IV);
      byte[] array;
      using(Aes aes = Aes.Create())
      {
        aes.Key = Encoding.UTF8.GetBytes(key);
        aes.IV = iv;
        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        using(MemoryStream memoryStream = new MemoryStream())
        {
          using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
          {
            using(StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
            {
              streamWriter.Write(data);
            }
            array = memoryStream.ToArray();
          }
        }
      }
      return Convert.ToBase64String(array);
    }



    public static string Decrypt(string data, string key)
    {
      string IV = key.Substring(0, 16);
      byte[] iv = Encoding.UTF8.GetBytes(IV);
      byte[] buffer = Convert.FromBase64String(data);
      using(Aes aes = Aes.Create())
      {
        aes.Key = Encoding.UTF8.GetBytes(key);
        aes.IV = iv;
        ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        using(MemoryStream memoryStream = new MemoryStream(buffer))
        {
          using(CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
          {
            using(StreamReader streamReader = new StreamReader((Stream)cryptoStream))
            {
              return streamReader.ReadToEnd();
            }
          }
        }
      }
    }
}

C代码的输出为:

 Encrypted: SORoNS48u0KniiANU3Y9Mw==
 Decrypted: test

node .js代码然后对此进行解密(使用相同的密钥和IV):

 Encrypted (base64): SORoNS48u0KniiANU3Y9Mw=
 Decrypted: test

Javascript相关问答推荐

提交表格后保留Web表格中的收件箱值?

fs. writeFile()vs fs.writeFile()vs fs.appendFile()

Javascript,部分重排序数组

如何解决chrome—extension代码中的错误,它会实时覆盖google—meet的面部图像?'

MathJax可以导入本地HTML文档使用的JS文件吗?

在JS中拖放:检测文件

使用领域Web SDK的Vite+Vue应用程序中的Web程序集(WASM)错误

基于props 类型的不同props ,根据来自接口的值扩展类型

Rxjs流中生成IMMER不能在对象上操作

在表单集中保存更改时删除';禁用';

如何使用Astro优化大图像?

构建器模式与参数对象输入

在没有任何悬停或其他触发的情况下连续交换图像

谷歌饼图3D切片

为什么当雪碧的S在另一个函数中时,Phaser不能加载它?

如何使pdf.js上的文本呈现为可选?

Js问题:有没有办法将数据从标记表转换成图表?

已在EventListener中更新/更改异步的React.js状态对象,但不会导致组件重新呈现

在openstreemap/leaflet中,当鼠标在 map 上移动时,如何在小工具提示中实时显示坐标

如何在Angular中运行没有哈希的项目