javascript - crypto-js 输出与 Node 加密不同

标签 javascript node.js encryption cryptography cryptojs

我们正在尝试匹配 crypto 和 crypto-js 输出。 我们的要求是在浏览器中加密字符串,但加密不支持浏览器端加密。因此,我们尝试使用 crypto-js 来匹配输出。每次 crypto-js 都会产生不同的输出。

const crypto = require('crypto');
const CryptoJS = require('crypto-js');

const payload = {
    name: 'John Doe'
}

// Node Package
function encryptNode(text) {
    const cipher = crypto.createCipher('aes-256-cbc', 'devOps');
    return cipher.update(Buffer.from(JSON.stringify(text)), 'utf8', 'hex') + cipher.final('hex');
}
console.log(encryptNode(payload));


// Browser Package
function encryptBrowser(text) {
    const ciphertext = CryptoJS.AES.encrypt(JSON.stringify(text), 'devOps', { mode: CryptoJS.mode.CBC });
    return ciphertext.toString(CryptoJS.format.Hex);
}
console.log(encryptBrowser(payload));

输出:

加密(预期):dfe03c7e825e9943aa6ec61deb4a8a73fdba0016a13c59c628ce025f39d44c7c

加密-js:4e5453abe7bd53d67d88aa4f040356c649fe0101366d05ce4c7d625cfd052cdc

最佳答案

crypto.createCipherCryptoJS.AES.encrypt利用 OpenSSL 函数的功能 EVP_BytesToKey ,它需要一个密码、一个可选的 8 字节盐、一个摘要和一个迭代计数,并根据这些数据生成一个 key 和一个 IV。这两个函数都使用 MD5 摘要和迭代计数 1 作为固定参数。

crypto.createCipher 不使用盐,因此每次都会生成相同的 key 和 IV,从而生成相同的密文(假设相同的明文)。

相比之下,CryptoJS.AES.encrypt 每次都会生成随机盐( herehere ),以便生成不同 key 和 IV每次都会产生不同的密文(即使是相同的明文)。为了解密(除了密码之外),需要盐,它不是 secret 的,可以与密文一起传递(例如在 CipherParams 对象中传递给 CryptoJS.AES.decrypt)。

因此,发布的代码片段的行为符合预期:使用 crypto.createCipher 创建的密文不会更改,使用 CryptoJS.AES.encrypt 创建的密文 每次都会改变。

EVP_BytesToKeyweak并且出于安全原因不应使用(至少在使用 MD5 且迭代计数为 1 时)。这同样适用于 crypto.createCipher (由于缺少 salt,更是如此),它无论如何都已被弃用,以及 CryptoJS.AES.encrypt 的重载变体,它使用EVP_BytesToKey。这两个库都提供了额外的或重载的方法,可以直接将 key 和 IV 传递给这些方法(如果需要,可以使用安全过程预先从密码派生)。

关于javascript - crypto-js 输出与 Node 加密不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59345650/

相关文章:

javascript - 如何为 margin-top 分配最大限制

javascript - 获取Electron网络框架的CSS选择器

javascript - 如何在菜单外部添加单击按钮以打开新的文本字段,而不是单击 "other"?

javascript - 递归加密以 'id' 或 '_id' 结尾的属性

javascript - 通过结构化 Express 应用程序提供 html 和 javascript

javascript - 断开 sails.js socket.io 的逻辑

objective-c - 指定在 OSX 上创建数字签名的填充

mysql - AES_ENCRYPT/AES_DECRYPT 中不正确的字符串值错误

javascript - 如何在客户端(AngularJS)加密密码,将其发送到服务器(expressJS)并在服务器上解密?

javascript - jQuery 在 Chrome 和 IE 中对数组输出进行不需要的排序(FF 工作正常)