【问题标题】:Matching Node.js aes-128-ecb (hex) encryption with C# .NET Core 3.1将 Node.js aes-128-ecb (hex) 加密与 C# .NET Core 3.1 匹配
【发布时间】:2021-12-09 17:54:33
【问题描述】:

我正在使用一个外部 API,它期望请求正文使用 aes-128-ecb(十六进制)加密。我使用 Node.js 和以下代码让它与 JavaScript 一起工作(每个会话使用相同的密钥,但这不是问题):

    var crypto = require('crypto'),
        algorithm = 'aes-128-ecb',
        key = 'E572F45E8D79CAF92B4BD3B375820831';

    var fetchlist = {
        fetch_list: '[{"name":"itemInfo","controller":"catalog.BLCCatalogItem","method":"getDetailWithColor","params":[264,86]}]',
    };
    var message = JSON.stringify(fetchlist);

    var cipher = crypto.createCipher(algorithm, key);
    var crypted = cipher.update(message, 'utf8', 'hex');
    crypted += cipher.final('hex');

我现在还想从我的 C# .NET Core 3.1 执行一些请求。应用程序,但无论我尝试什么,我都没有得到相同的结果。 API 也不接受我的请求。

        var fetchList = new FetchList();
        fetchList.fetch_list = "[{\"name\":\"itemInfo\",\"controller\":\"catalog.BLCCatalogItem\",\"method\":\"getDetailWithColor\",\"params\":[264,86]}]";
        string message = JsonConvert.SerializeObject(fetchList);

        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        aes.BlockSize = 128;
        aes.KeySize = 128;
        aes.Key = UTF8Encoding.UTF8.GetBytes(Key);
        aes.Mode = CipherMode.ECB;
        aes.Padding = PaddingMode.PKCS7;
        byte[] data = Encoding.UTF8.GetBytes(message);

        ICryptoTransform encrypt = aes.CreateEncryptor();

        byte[] dest = encrypt.TransformFinalBlock(data, 0, data.Length);

        StringBuilder hex = new StringBuilder(dest.Length * 2);
        foreach (byte b in dest)
            hex.AppendFormat("{0:x2}", b);
        var output =  hex.ToString();

和 FetchList 类:

public class FetchList
{
    public string fetch_list { get; set; }
}

【问题讨论】:

  • createCipher() 将第二个参数解释为密码并从中派生密钥。该方法已弃用,应替换为createCipheriv()。密钥必须经过十六进制解码为 16 字节大小并与 AES-128-ECB 兼容。请注意,ECB 是一种不安全的模式。
  • 正如我指出的问题出在 C# 部分,JavaScript 到目前为止工作正常(不推荐使用的 createCipher() 除外。感谢您,将检查这一点)。 API 是外部的,所以我没有选择 ECB。
  • 如果你想保留createCipher(),你必须在C#代码中用EVP_BytesToKey()派生密钥。互联网上有 C# 的实现。我建议不要这样做,EVP_BytesToKey() 不安全且不推荐使用(这就是不推荐使用 createCipher() 的原因)。最好切换到createCipheriv()。关于 C# 代码:C# 代码似乎也缺少密钥的十六进制解码。您确定message 的 Utf8 编码在两个代码中是相同的吗?无法验证,因为我找不到 FetchList
  • 谢谢,将与EVP_BytesToKey() 一起尝试。 FetchList 只是一个简单的类,它具有一个字符串类型的属性,用于获取与 JavaScript 中相同的对象。我在最初的帖子中添加了它。该消息不包含任何需要首先保护的内容,所以我猜它背后的想法是加密请求正文。
  • EVP_BytesToKey() 的可能实现可以在here 中找到。 createCipher() 不使用盐,因为摘要 MD5 和迭代计数为 1(网络上也有更精简的实现已经考虑到丢失的盐和迭代计数 1)。如果您将E572F45E8D79CAF92B4BD3B375820831 解释为密码,从技术角度来看,AES-128 的十六进制解码是不必要的。

标签: c# aes asp.net-core-3.1


【解决方案1】:

感谢@Topaco,我能够解决我的问题。下面是代码现在的样子:

        var key = new OpenSslCompatDeriveBytes(UTF8Encoding.UTF8.GetBytes("E572F45E8D79CAF92B4BD3B375820831"), null, "MD5", 1).GetBytes(16);

        var fetchList = new FetchList();
        fetchList.fetch_list = "[{\"name\":\"itemInfo\",\"controller\":\"catalog.BLCCatalogItem\",\"method\":\"getDetailWithColor\",\"params\":[137696,115]}]";
        string message = JsonConvert.SerializeObject(fetchList);

        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        aes.BlockSize = 128;
        aes.KeySize = 128;
        aes.Key = key;
        aes.Mode = CipherMode.ECB;
        aes.Padding = PaddingMode.PKCS7;
        byte[] data = Encoding.UTF8.GetBytes(message);

        ICryptoTransform encrypt = aes.CreateEncryptor();

        byte[] dest = encrypt.TransformFinalBlock(data, 0, data.Length);

        StringBuilder hex = new StringBuilder(dest.Length * 2);
        foreach (byte b in dest)
            hex.AppendFormat("{0:x2}", b);
        var output =  hex.ToString();

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多