crypto-js输出与节点crypto不同

时间:2019-12-15 16:10:40

标签: 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));

输出:

crypto(预期):dfe03c7e825e9943aa6ec61deb4a8a73fdba0016a13c59c628ce025f39d44c7c

crypto-js:4e5453abe7bd53d67d88aa4f040356c649fe0101366d05ce4c7d625cfd052cdc

1 个答案:

答案 0 :(得分:2)

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

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

相反,CryptoJS.AES.encrypt每次都会生成随机盐(herehere),因此每次都会生成 different 键和IV,因此是不同的密文(即使是相同的明文)。为了解密(在密码旁边),需要加盐,这不是秘密,可以与密文一起传递(例如,在CipherParams对象中传递给CryptoJS.AES.decrypt)。

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

EVP_BytesToKeyweak,出于安全考虑,不应使用

crypto.createCipher(至少在使用MD5且迭代计数为1时)。同样适用于CryptoJS.AES.encrypt(由于缺少盐而更是如此)(无论如何都已弃用)和EVP_BytesToKey的重载变体,后者使用let ordersArray = [ {"snapshotKey":"-awdawadsdwwd","username":"Joe"}, {"snapshotKey":"-badsdasdad","username":"Annna"}, {"snapshotKey":"-dasQwaddas","username":"lee"} ] let rejectedOrders = ["-awdawadsdwwd","-dasQwaddas"] //these orders snapshot keys 。这两个库都提供了其他的或重载的方法,可以直接将 传递密钥和IV(可以根据需要使用安全过程预先从密码短语中获得密钥和IV)。