javascript - 将 Node 加密 aes-256-cbc 转换为 CryptoJS

标签 javascript node.js aes cryptojs node-crypto

如何转换以下Node的内置crypto module encryptionCryptoJS

const crypto = require('crypto');

const pass = 'some,password:)with>spec(chars*'
const cipher1 = crypto.createCipher('aes-256-cbc', pass)
const c1 = cipher1.update(input, 'utf8', 'hex') + cipher1.final('hex')

我试过类似的东西,但结果不一样:

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

const pass = 'some,password:)with>spec(chars*'
const cipher2 = CryptoJS.AES.encrypt(input, pass, {
    mode: CryptoJS.mode.CBC,
});
const c2 = cipher2.ciphertext.toString(CryptoJS.enc.Hex);

我需要将其用作 Postman 预请求脚本,因为它不支持 Node 的 crypto,但支持 crypto-js

最佳答案

两个代码都使用 OpenSSL 专有 key 派生函数 EVP_BytesToKey(),迭代计数为 1,MD5 作为摘要。
NodeJS 不使用盐,而 CryptoJS 使用随机盐。出于这个原因,每次加密的 NodeJS 结果都不会改变,而 CryptoJS 结果总是会改变(假设相同的明文和密码)。

因此,要使用 CryptoJS 代码获取 NodeJS 代码的结果,您不能使用盐。但是,默认情况下,总是应用盐。这只能通过使用 key 派生函数明确确定 key 和 IV 来规避 EvpKDF然后在加密中使用两者:

var input = "The quick brown fox jumps over the lazy dog";
var pass = 'some,password:)with>spec(chars*'

var keySize = 32/4;
var ivSize = 16/4;
var kdf = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize, hasher: CryptoJS.algo.MD5 }).compute(pass, ''); // no salt!
var key = CryptoJS.lib.WordArray.create(kdf.words.slice(0, keySize), keySize * 4);
var iv = CryptoJS.lib.WordArray.create(kdf.words.slice(keySize), ivSize * 4);
var ciphertextCP = CryptoJS.AES.encrypt(input, key, {iv: iv}); // default: CBC, PKCS#7 padding
var ciphertext = ciphertextCP.ciphertext.toString(CryptoJS.enc.Hex);
document.getElementById("ct").innerHTML = ciphertext; // d98cf2d285bf0c1d796226190bf54d9c5540300ee1c6f35618f8bb3564b5053920ec958d31b41bbe4e4880e23543d709
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="ct"></p>

此 CryptoJS 代码为与 NodeJS 代码相同的明文和密码生成相同的密文。


请注意,使用 EVP_BytesToKey() 和所选参数的 key 派生已被弃用,并且在今天被认为是不安全的。由于缺少盐,NodeJS 在很大程度上比 CryptoJS 更真实。

避免内置 key 推导函数,直接指定 key 更安全。
为此,请在 NodeJS 中使用 createCipheriv() 并在 CryptoJS 代码中将 key 作为 WordArray 传递。这样,每次加密都必须显式生成一个随机 IV。
可选地,可以使用可靠的 key 派生函数,如 PBKDF2,这两个库都支持。

关于javascript - 将 Node 加密 aes-256-cbc 转换为 CryptoJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70658455/

相关文章:

java - 接收到的字节数组与发送的字节数组具有不同的值,AES 加密 + IV

javascript - Materializecss 工具提示不适用于 Angularjs

javascript - Fancybox 2 iframe 在 IE 中无法正常工作

javascript - 关闭模态对话框屏幕

node.js - 是否可以使用 Azure Key Vault 的 Keys API 创建 JSON Web token ?

javascript - 错误的编译顺序

javascript - 如何使用 Intern JS 要求模块来测试 NodeJS?

cocoa - 有AES加密解密的cocoa源代码吗?

MySQL aes_encrypt 填充方案?

javascript - 在具有单个 HTML 文件的两个图像之间切换