node.js - 这个 C# 加密代码在 NodeJS 中会是什么样子?

标签 node.js encryption

tripledes encryption not yielding same results in PHP and C#

    public static string Encrypt(string toEncrypt, string key, bool useHashing) 
    {     
        byte[] keyArray;     
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);      

        if (useHashing)     
        {         
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));     
        }     
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);      

        TripleDESCryptoServiceProvider tdes 
            = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;     
        tdes.Mode = CipherMode.ECB;     
        tdes.Padding = PaddingMode.PKCS7;      

        ICryptoTransform cTransform = tdes.CreateEncryptor();     
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
            toEncryptArray.Length);      
        return Convert.ToBase64String(resultArray, 0, resultArray.Length); 
    }  

上面的帖子和代码有一些非常简单的(或者我认为的)逻辑来使用 3DES 和私钥加密/解密字符串。

我发现了一些如何使用 crypt 库在 Nodejs 中实现类似功能的示例,但到目前为止我尝试过的所有内容都产生了垃圾(理所当然)。

想法?

更新1:

下面是一些用于生成我正在使用的数据的 C# 代码:

    String key = "abcdefghijklmnop";
    String text = "12345";
    String encrypted = Encrypt(text, key, false);
    //Returns "QI3I65+aWSk="

这是我正在使用的 Nodejs 代码的最新版本:

    var crypto = require('crypto');
    var key = 'abcdefghijklmnop';
    var encrypted = 'QI3I65+aWSk=';
    var expected = '12345';

    var algs = [ 'des3', 'des-ede', 'des-ede3', 'des-ecb', 'aes-128-ecb'];
    for(var i in algs)
    {
      var decipher = crypto.createDecipher(algs[i], key);
      var result = ''
      result += decipher.update(encrypted, 'hex', 'binary');
      result += decipher.final('binary');

      console.log('Algorithm: ' + algs[i] 
        + ', Matched Expected: ' + (result === expected));
    }

.. 返回

    Algorithm: des3, Matched Expected: false
    Algorithm: des-ede, Matched Expected: false
    Algorithm: des-ede3, Matched Expected: false
    Algorithm: des-ecb, Matched Expected: false
    Algorithm: aes-128-ecb, Matched Expected: false

我不清楚到底要使用哪种算法(我的列表在之前的尝试中明显更长),现在我确定要使用哪种编码组合(二进制/十六进制)。

再次感谢。

更新2: 从引用的帖子中复制了加密方法:

tripledes encryption not yielding same results in PHP and C#

最佳答案

好吧,我花了一段时间才弄清楚这件事的真相。

首先关于DES算法,DES算法需要一个IV(初始向量)来加密,以及 key System.Security.Cryptography 中的 DES 算法将生成 IV randomly当没有指定时。解密时,您需要 key IV

这就是为什么你的代码永远不会工作,因为你的解密程序只是不知道加密中使用的 IV,并且会自己生成另一个 IV,它与随机的 IV 不匹配。

其次,你的 javascript 代码在很多地方都是错误的:

decipher.update(encrypted, 'hex', 'binary')

其中加密不是以十六进制编码而是以base64编码,并且您需要将结果输出为base64而不是二进制。 阅读document .

['des3'、'des-ede'、'des-ede3'、'des-ecb'、'aes-128-ecb']

其中所有这些算法都与您使用的加密算法不同。正如您指定使用 CipherMode.ECB ,即 not recommended而且openssh根本不支持,所以无法解密。

所有这些加起来,你的代码将无法工作。

以下是正确的做法:

using System;
using System.Text;
using System.Security.Cryptography;

public class Test
{
    public static string Encrypt(string toEncrypt, string key, bool useHashing) 
    {     
        byte[] keyArray;     
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);      

        if (useHashing)     
        {         
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));     
        }     
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);      

        var tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;     
        // tdes.Mode = CipherMode.CBC;  // which is default     
        // tdes.Padding = PaddingMode.PKCS7;  // which is default

        Console.WriteLine("iv: {0}", Convert.ToBase64String(tdes.IV));

        ICryptoTransform cTransform = tdes.CreateEncryptor();     
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
            toEncryptArray.Length);      
        return Convert.ToBase64String(resultArray, 0, resultArray.Length); 
    }  

    public static void Main()
    {
        Console.WriteLine("encrypted as: {0}", Encrypt("12345", "abcdefghijklmnop", false));
    }
}

输出

iv: pdMBMjdeFdo=
encrypted as: 3uDkdT6aQ3c=

并在node.js中使用正确的算法des-ede-cbc:

var crypto = require('crypto');

var alg = 'des-ede-cbc';

var key = new Buffer('abcdefghijklmnop', 'utf-8');
var iv = new Buffer('pdMBMjdeFdo=', 'base64');

var encrypted = new Buffer('3uDkdT6aQ3c=', 'base64');
var source = '12345';

var cipher = crypto.createCipheriv(alg, key, iv);
var encoded = cipher.update(source, 'ascii', 'base64');
encoded += cipher.final('base64');

console.log(encoded, encrypted.toString('base64'));

var decipher = crypto.createDecipheriv(alg, key, iv);
var decoded = decipher.update(encrypted, 'binary', 'ascii');
decoded += decipher.final('ascii');

console.log(decoded, source);

输出

3uDkdT6aQ3c= 3uDkdT6aQ3c=
12345 12345

现在问题解决了。

关于node.js - 这个 C# 加密代码在 NodeJS 中会是什么样子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8889547/

相关文章:

Python3 Cryptodome - 如何解密pem?

java - Android NDK中的解密

javascript - 使用babel-node调试ES6 Node.js应用程序

node.js - 使用 Nodejs 的 Firebase 电话身份验证

c# - 如何将图像字节数组解密为原始值?

Java 等效于 C# AES 加密

c - 如何从客户端向服务器发送无效密码?

javascript - "Error: MongooseError: Operation ` users.insertOne() ` buffering timed out after 10000ms",

PHP:shell_exec 一个 shell 脚本与 shell_exec 一个 linux 上的程序(权限)

node.js - npm 安装的默认包版本是什么