我们正在努力匹配密码和密码的输出。我们的要求是在浏览器中加密字符串,但是密码不支持浏览器端加密。因此,我们试图使用密码-js匹配输出。每次密码-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
发布于 2019-12-15 20:47:42
crypto.createCipher和CryptoJS.AES.encrypt利用OpenSSL函数EVP_BytesToKey的功能,它需要一个密码、一个可选的8字节盐、一个摘要和一个迭代计数,并从这些数据中生成一个密钥和一个IV。这两个函数都使用MD5摘要和迭代计数1作为固定参数。
crypto.createCipher不使用salt,因此每次生成相同的密钥和IV,从而生成相同的密文(假设相同的明文)。
相反,CryptoJS.AES.encrypt每次生成一个随机盐(这里和这里),因此每次生成不同的密钥和IV,从而生成不同的密文(即使是相同的明文)。为了解密(密码旁边),需要salt,它不是秘密的,可以与密文一起传递(例如,在CipherParams-object to CryptoJS.AES.decrypt中)。
因此,发布的代码片段的行为与预期相同:使用crypto.createCipher创建的密文不会改变,用CryptoJS.AES.encrypt创建的密文每次都会更改。
EVP_BytesToKey是瘦弱,不应该出于安全考虑而使用(至少在使用MD5和迭代次数为1时如此)。同样的情况也适用于crypto.createCipher (更多的是因为缺少了salt),它无论如何都是不推荐的,而重载的CryptoJS.AES.encrypt变体使用EVP_BytesToKey。这两个库都提供了额外的或重载的方法,可以将密钥和IV直接传递给它们(如果需要的话,这些方法可以事先使用安全过程从密码中派生)。
https://stackoverflow.com/questions/59345650
复制相似问题