gpt4 book ai didi

node.js - 在 Node.js 中使用 Crypto 加密未给出预期结果

转载 作者:行者123 更新时间:2023-12-04 14:52:06 25 4
gpt4 key购买 nike

我有一个旧的嵌入式设备,它需要一个带有给定密码、 key 和 IV 的加密密码。用 .NET 框架编写的现有应用程序创建了一个 AES-128-CBC 加密字符串,我正在使用 Crypto 库在 Node.js 中重写它。

但是,当我在 Node.js 中使用相同的 key 和 IV 加密字符串时,输出与在 .NET 中不同。我已经使用在线工具仔细检查了加密,它们产生的结果与 .NET 相同,因此 Node.js Crypto 是一个奇怪的选择。

.NET 的 C# 代码( key 和 IV 已被替换为演示目的):

byte[] encrypted;

using (AesManaged aes = new AesManaged())
{
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.Zeros;
aes.Key = new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
aes.IV = new byte[] { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 };

ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write("admin");
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;

这给出了 Base64 字符串 gE1twb8LV/44oO/6UKwwCg==。我使用在线工具测试了相同的密码、 key 和 IV,它们给出了相同的输出。

我的 Node.js 代码:

const crypto = require('crypto');

const key = Buffer.from('00112233445566778899aabbccddeeff', 'hex');
const iv = Buffer.from('aabbccddeeff00112233445566778899', 'hex');

const plaintext = 'admin';
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
cipher.update(Buffer.from('admin'));
var encrypted = cipher.final().toString('base64');

这给出了 Base64 字符串 4TT9E4WDH/TmlKjJdVFeHQ==

我已经尝试了所有我能想到的方法,但都没有成功。我注意到 .NET 代码指定了零填充,但我一直无法找到在 Node.js Crypto 中设置它的方法。我猜这可能就是它不提供相同输出的原因。

有人知道如何在 Node.js Crypto 中指定零填充吗?

最佳答案

正如您已经注意到的,填充不匹配。在 C# 代码中指定零填充,在 NodeJS 代码中默认使用 PKCS#7。由于 NodeJS 的 crypto 模块不支持零填充,您必须自己实现它并禁用默认填充。

此外,必须为 update()final() 调用定义输入和输出编码,并且必须连接这些部分。在以下 NodeJS 代码中,UTF-8 被指定为输入编码,Base64 被指定为输出编码:

const crypto = require('crypto');

const key = Buffer.from('00112233445566778899aabbccddeeff', 'hex');
const iv = Buffer.from('aabbccddeeff00112233445566778899', 'hex');

const plaintext = 'admin';
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
cipher.setAutoPadding(false); // Disable default PKCS#7 padding
var paddedPlaintext = zeroPad(plaintext, 16); // Zero pad plaintext
var encrypted = cipher.update(paddedPlaintext, 'utf8', 'base64'); // Specify input-/outputencoding
encrypted += cipher.final('base64'); // Specify outputencoding and concatenate
console.log(encrypted); // gE1twb8LV/44oO/6UKwwCg==

function zeroPad(text, bs){
var padLength = text.length;
if (text.length % bs > 0){
padLength += bs - text.length % bs;
}
return text.padEnd(padLength, '\0');
}

输出:

gE1twb8LV/44oO/6UKwwCg==

与 C# 代码的输出匹配。


请注意,静态 IV 是不安全的。为每次加密使用随机生成的 IV 更安全。当然,出于测试目的,这很好。
此外,零填充是不可靠的。更好的选择是 PKCS#7 填充(这是 crypto 默认值)。

关于node.js - 在 Node.js 中使用 Crypto 加密未给出预期结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68914125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com