Ken*_* Ki 3 javascript cryptojs
如本答案所述,我可以使用 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)Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>Run Code Online (Sandbox Code Playgroud)
我得到:
U2FsdGVkX19blKXDRXfdgXyviCrZtouB0cPcJPoR/cQ= U2FsdGVkX1+1AwWqKWntLVkh7DtiZxPDYCDNsjmc8LM= false
Run Code Online (Sandbox Code Playgroud)
难道我做错了什么?有没有办法达到预期的结果?
首先:对于相同的明文和相同的密钥,在ECB模式下总是生成相同的密文!
如果 aWordArray用作第二个参数,则使用密钥CryptoJS.AES.encrypt执行加密并且生成的密文与预期相同(此处):
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);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>Run Code Online (Sandbox Code Playgroud)
但是,如果将字符串用作第二个参数,则使用密码CryptoJS.AES.encrypt进行加密并且生成的密文是不同的(此处)。尽管如此,解密当然会返回原始明文:
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');Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>Run Code Online (Sandbox Code Playgroud)
说明:
在使用密码进行加密的过程中,会生成一个随机的8 字节盐,与密码一起生成实际密钥(32 字节,AES-256)。
盐的目的是使彩虹表的使用不可行。由于每次都会随机生成盐,因此生成的密钥不同,因此密文也不同。CryptoJS.AES.encrypt返回一个CipherParams对象,该对象封装了相关参数,如盐和实际密文。toString()将此对象转换为 OpenSSL 格式,该格式由 的 ASCII 编码组成Salted__,后跟 8 个字节的盐,然后是实际的密文,所有这些都是 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');Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>Run Code Online (Sandbox Code Playgroud)
详细信息:
CryptoJSEVB_BytesToKey在派生密钥时使用带有摘要 MD5 和迭代计数 1的 OpenSSL 功能,这不是很安全。更安全的是使用可靠的 KDF,例如 PBKDF2,然后使用生成的密钥进行加密。
除了安全性之外,应该注意的是,EVB_BytesToKey它没有实现标准,因此必须首先在不可用的库中实现(或从 Internet 复制)此功能。
注意: ECB 是一种不安全的模式,不应该使用(这里),更好的是像 GCM 这样的身份验证加密。有关 CryptoJS 的更多详细信息,请参见其文档(此处)。
| 归档时间: |
|
| 查看次数: |
2473 次 |
| 最近记录: |