Nodejs求助:使用node的crypto模块,对由C#加密过的数据进行解密,结果与C#解密的结果不一致。(注:加密使用相同的KEY和IV)

Nodejs求助:使用node的crypto模块,对由C#加密过的数据进行解密,结果与C#解密的结果不一致。(注:加密使用相同的KEY和IV)

    ==========  C#代码  ==========
private static byte[] KEY = { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] IV = { 1, 2, 3, 4, 5, 6, 7, 8 };
public static string EncryptDes(string input)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
MemoryStream ms = null;
CryptoStream encStream = null;
StreamWriter sw = null;
string result = String.Empty;

    try
    {
        ms = new MemoryStream();
        encStream = new CryptoStream(ms, des.CreateEncryptor(KEY, IV), CryptoStreamMode.Write);

        // Create a StreamWriter to write a string
        // to the stream.
        sw = new StreamWriter(encStream);

        // Write the plaintext to the stream.
        sw.WriteLine(input);

        sw.Flush();
        encStream.FlushFinalBlock();
        ms.Flush();

        byte[] bytes = ms.GetBuffer();
        Console.WriteLine(BitConverter.ToString(bytes, 0, 24));

        result = Convert.ToBase64String(bytes, 0, Convert.ToInt32(ms.Length, CultureInfo.InvariantCulture));
    }
    finally
    {
        //close objects
    }
    return result;
}

==========  Node.js代码  ==========

var crypto = require(‘crypto’); var KEY = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; var IV = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; exports.encryptDes = function(input){ var cipher = crypto.createCipheriv(‘des’, new Buffer(KEY), new Buffer(IV)); var buf1 = cipher.update(input, ‘utf8’); var buf2 = cipher.final(); var result = new Buffer(buf1.length + buf2.length); buf1.copy(result); buf2.copy(result, buf1.length);

return result.toString('base64');

};


6 回复

为了解决这个问题,我们需要确保Node.js中的crypto模块与C#中的DESCryptoServiceProvider行为一致。主要问题可能在于填充方式、编码以及最终的数据处理。

C# 代码分析

C#代码中使用了DESCryptoServiceProvider来加密数据,并且使用了StreamWriter将字符串写入流中。这里需要注意的是,StreamWriter默认使用UTF-8编码。

Node.js 代码调整

在Node.js中,我们需要确保加密时使用相同的填充方式和编码方式。以下是调整后的Node.js代码:

const crypto = require('crypto');

// 定义密钥和初始化向量
const KEY = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
const IV = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);

function encryptDes(input) {
    const cipher = crypto.createCipheriv('des-cbc', KEY, IV);
    
    // 使用utf8编码
    let encrypted = cipher.update(input, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    
    return encrypted;
}

console.log(encryptDes("Hello World"));  // 输出加密后的字符串

解密函数

为了验证解密是否正确,我们可以编写一个解密函数:

function decryptDes(encrypted) {
    const decipher = crypto.createDecipheriv('des-cbc', KEY, IV);
    
    // 使用base64解码
    let decrypted = decipher.update(encrypted, 'base64', 'utf8');
    decrypted += decipher.final('utf8');
    
    return decrypted;
}

const encryptedData = "Hello World";  // 这里应替换为实际加密后的字符串
console.log(decryptDes(encryptedData));  // 输出解密后的字符串

关键点解释

  1. 填充方式:C#默认使用PKCS7填充,Node.js也需要使用相同的填充方式。
  2. 编码:在加密和解密过程中,确保使用相同的编码(如UTF-8)。
  3. 算法选择:在Node.js中,我们使用'des-cbc'而不是直接使用'des',以确保与C#的行为一致。

通过以上步骤,可以确保Node.js和C#的加密解密过程一致。如果仍然存在问题,建议检查输入数据的格式和长度,因为DES算法对输入数据有特定的要求。


我也碰到过类似的,我当时是用C加密,node解密,C加密的时候是没有IV这个参数的,node解密的时候IV向量用的是16字节的0,结果和C保持一致了。只知道这么解决了,资料比较少,当时没有搞懂,现在同求大神解答。 ps:C不是很懂,依样画葫芦,使用的时候只需要传一个key参数就可以了,而node是有两种方法的,当时我就混乱了

主要是以前C#的系统中使用了 IV 这个变量来加密,所以Node这边要解密C#那边遗留下的数据的话,按理说两边是需要使用相同的 IV 向量的。问题是现在两边都用同一个 IV,但是出来的结果却不一样。网上相关的资料也很少,只能等大神来解答~

每个加密算法的实现都是有差异的,网上找找跨语言的加密库。

哈哈,刚刚把问题解决了。原来上面C#代码在使用StreamWriter写加密流的时候使用了 sw.WriteLine(input) 这个方法,导致了最后多了两个字节(0D, 0A),而Node那边因为少了这两个字节,所以加密出来的结果不一样。 刚刚我手动给Node的数据加上0D, 0A两个字节后,加密出来的结果是一样的。所以我想Node和.NET在对DES加密算法的实现应该是一样的吧。不过还是谢谢你的热心回答~

为了确保Node.js中的解密结果与C#中的解密结果一致,我们需要考虑一些细节问题,如填充方式、字符编码等。以下是一个可能的解决方案,展示了如何使用Node.js的crypto模块正确地解密由C#加密的数据。

示例代码

C#加密代码

public static string EncryptDes(string input)
{
    var des = new DESCryptoServiceProvider();
    var ms = new MemoryStream();
    var encStream = new CryptoStream(ms, des.CreateEncryptor(KEY, IV), CryptoStreamMode.Write);
    var sw = new StreamWriter(encStream);

    sw.WriteLine(input);
    sw.Flush();
    encStream.FlushFinalBlock();
    ms.Flush();

    var result = Convert.ToBase64String(ms.ToArray());
    return result;
}

Node.js解密代码

var crypto = require('crypto');

var KEY = [1, 2, 3, 4, 5, 6, 7, 8];
var IV = [1, 2, 3, 4, 5, 6, 7, 8];

function decryptDes(ciphertext) {
    var decipher = crypto.createDecipheriv('des-cbc', Buffer.from(KEY), Buffer.from(IV));
    var decrypted = decipher.update(ciphertext, 'base64', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}

// 测试
var ciphertext = "YourEncryptedTextHere"; // 替换为实际的加密文本
console.log(decryptDes(ciphertext)); // 输出解密后的明文

解释

  1. 加密方式:C#代码中使用的是DES算法,Node.js代码中也应使用相同的算法(des-cbc)。
  2. 字符编码:在解密时,输入的密文需要指定为base64格式,并且解密后的输出应转换为utf8编码。
  3. 填充方式:C#默认使用PKCS7填充,Node.js的crypto模块也需要设置相同的填充方式。可以通过传递一个选项对象来实现:
var decipher = crypto.createDecipheriv('des-cbc', Buffer.from(KEY), Buffer.from(IV));
decipher.setAutoPadding(true); // 确保使用PKCS7填充

通过以上步骤,可以确保Node.js解密结果与C#解密结果一致。

回到顶部