gpt4 book ai didi

javascript - 使用 ECB 模式的 CryptoJS AES 加密使用相同的参数产生不同的结果

转载 作者:行者123 更新时间:2023-12-04 01:31:04 29 4
gpt4 key购买 nike

如本文所述 answer ,我可以使用 ECB 模式将转换后的值反转回纯文本,而不仅仅是将其与另一个散列值进行比较。

但是,使用以下代码片段:

const x = CryptoJS.AES.encrypt('abc', '123', { mode: CryptoJS.mode.ECB }).toString()
const y = CryptoJS.AES.encrypt('abc', '123', { mode: CryptoJS.mode.ECB }).toString()

console.log(x, y, x === y)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>


我得到:
U2FsdGVkX19blKXDRXfdgXyviCrZtouB0cPcJPoR/cQ= U2FsdGVkX1+1AwWqKWntLVkh7DtiZxPDYCDNsjmc8LM= false

难道我做错了什么?有没有办法达到预期的结果?

最佳答案

首先:对于相同的明文和相同的 key ,ECB 中总是生成相同的密文。模式!

如果一个 WordArray用作第二个参数,然后 CryptoJS.AES.encrypt使用 key 执行加密,得到的密文是 相同 正如预期的那样(here):

function encryptWithKey(plaintext, key){
var encrypted = CryptoJS.AES.encrypt(plaintext, key, { mode: CryptoJS.mode.ECB });
console.log("Ciphertext (Base64):\n" + encrypted.toString()); // Ciphertext
var decrypted = CryptoJS.AES.decrypt(encrypted.toString(), key, { mode: CryptoJS.mode.ECB });
console.log("Decrypted:\n" + decrypted.toString(CryptoJS.enc.Utf8)); // Plaintext
}

var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f');
encryptWithKey('abc', key);
encryptWithKey('abc', key);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>


但是如果使用字符串作为第二个参数, CryptoJS.AES.encrypt使用密码执行加密,得到的密文是 不同 ( here)。尽管如此,解密当然会返回原始明文:

function encryptWithPassphrase(plaintext, passphrase){
var encrypted = CryptoJS.AES.encrypt(plaintext, passphrase, { mode: CryptoJS.mode.ECB });
console.log("Ciphertext (OpenSSL):\n" + encrypted.toString()); // Salt and actual ciphertext in OpenSSL format
var decrypted = CryptoJS.AES.decrypt(encrypted.toString(), passphrase, { mode: CryptoJS.mode.ECB });
console.log("Decrypted:\n" + decrypted.toString(CryptoJS.enc.Utf8)); // Plaintext
}

encryptWithPassphrase('abc', '123');
encryptWithPassphrase('abc', '123');
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>


解释:

在使用密码加密期间,会生成一个随机的 8 字节盐,与密码一起生成实际 key (32 字节,AES-256)。盐旨在使彩虹表的使用不可行。由于盐每次都是随机生成的,因此生成的 key 不同,因此密文也不同。 CryptoJS.AES.encrypt返回 CipherParams 封装了盐和实际密文等相关参数的对象。 toString()将此对象转换为由 Salted__ 的 ASCII 编码组成的 OpenSSL 格式,然后是 8 个字节的 salt,然后是实际的密文,它们一起使用 Base64 编码。因此,所有密文都以 U2FsdGVkX1 开头。 .

function encryptWithPassphraseParams(plaintext, passphrase){
var encrypted = CryptoJS.AES.encrypt(plaintext, passphrase, { mode: CryptoJS.mode.ECB });
console.log("Salt (hex):\n" + encrypted.salt); // Salt (hex)
console.log("Key (hex):\n" + encrypted.key); // Key (hex)
console.log("Ciphertext (hex):\n" + encrypted.ciphertext); // Actual ciphertext (hex)
console.log("Ciphertext (OpenSSL):\n" + encrypted.toString()); // Salt and actual ciphertext, Base64 encoded, in OpenSSL format
console.log("\n");
}

encryptWithPassphraseParams('abc', '123');
encryptWithPassphraseParams('abc', '123');
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>


详情:
CryptoJS 使用 OpenSSL 功能 EVB_BytesToKey 导出 key 时使用摘要 MD5 和迭代计数 1,这不是很安全。更安全的是使用可靠的 KDF,例如 PBKDF2 以及随后使用生成的 key 进行加密。除了安全性之外,应该注意 EVB_BytesToKey没有实现标准,因此必须首先在不可用的库中实现(或从 Internet 复制)此功能。

注意:ECB 是一种不安全的模式,不应使用 ( here),更好的是像 GCM 这样的经过身份验证的加密。有关 CryptoJS 的更多详细信息可以在其文档 ( here) 中找到。

关于javascript - 使用 ECB 模式的 CryptoJS AES 加密使用相同的参数产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61046037/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com