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');
};
为了解决这个问题,我们需要确保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)); // 输出解密后的字符串
关键点解释
- 填充方式:C#默认使用PKCS7填充,Node.js也需要使用相同的填充方式。
- 编码:在加密和解密过程中,确保使用相同的编码(如UTF-8)。
- 算法选择:在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)); // 输出解密后的明文
解释
- 加密方式:C#代码中使用的是DES算法,Node.js代码中也应使用相同的算法(
des-cbc
)。 - 字符编码:在解密时,输入的密文需要指定为
base64
格式,并且解密后的输出应转换为utf8
编码。 - 填充方式:C#默认使用PKCS7填充,Node.js的
crypto
模块也需要设置相同的填充方式。可以通过传递一个选项对象来实现:
var decipher = crypto.createDecipheriv('des-cbc', Buffer.from(KEY), Buffer.from(IV));
decipher.setAutoPadding(true); // 确保使用PKCS7填充
通过以上步骤,可以确保Node.js解密结果与C#解密结果一致。