【发布时间】:2021-10-25 01:47:25
【问题描述】:
我有一个旧的嵌入式设备,它需要一个具有给定密码、密钥和 IV 的加密密码。一个用 .NET 框架编写的现有应用程序会创建一个 AES-128-CBC 加密字符串,我正在使用 Crypto 库在 Node.js 中重写它。
但是,当我在 Node.js 中使用相同的密钥和 IV 加密字符串时,输出与 .NET 中的不同。我已经使用在线工具仔细检查了加密,它们产生的结果与 .NET 相同,因此 Node.js Crypto 是一个奇怪的结果。
.NET 的 C# 代码(密钥和 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==。
我用在线工具测试了相同的密码、密钥和 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 中指定零填充吗?
【问题讨论】:
-
零填充是不安全的,NodeJS automatically provides PKCS padding which can be turned off。因此,如果您必须实现它,例如像在您的情况下保持兼容性,那么您必须自己实现填充。快速搜索发现this 和this,应该会给你一个想法。不想自己实现也可以搜索npm。
标签: node.js encryption aes cryptojs