我需要解密使用 AES 加密的传入请求,我尝试使用共享示例但无法找到正确的参数集
- 加密方式:AES/CBC/PKCS5Padding AES/CBC/PKCS5
- 初始化向量:长度为16的空字节数组
- 测试秘钥:1234567890123456
- 纯文本:abcdefghigklmnopqrstuvwxyz0123456789
- 加密:8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVERr
我接下来用
const cryptkey = '1234567890123456';
const cleardata = "abcdefghigklmnopqrstuvwxyz0123456789";
const crypted = "8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr";
var decrypt = CryptoJS.AES.decrypt(crypted, cryptkey, {
iv: CryptoJS.enc.Hex.parse('0000000000000000'),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
var ddd = decrypt.toString(CryptoJS.enc.Utf8);
console.log(ddd);
每次我得到空字符串。 我在哪里失败了?
------ 更新 -----
添加了评论的新版本,仍然不起作用
const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');
const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr");
var decrypt = CryptoJS.AES.decrypt(crypted, cryptkey, {
iv: CryptoJS.enc.Hex.parse('00000000000000000000000000000000'),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
最佳答案
您必须先解析 UTF-8 key :
const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');
如果您不这样做,CryptoJS 将假定它是一个密码并从中派生出实际的 key 。
正如 Maarten 也指出的...
密文也必须从 Base64 解码:
const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr");
请注意,解密器需要一个 CipherParams
对象,您可以通过将 {ciphertext: crypted}
传递给 decrypt
函数来模拟该对象。或者,您可以依靠 CryptoJS 从 Base64 解码密文,您按原样传入该字符串。
AES-CBC 的 IV 必须是 16 个字节长,如果编码为十六进制则为 32 个字符:
CryptoJS.enc.Hex.parse('00000000000000000000000000000000')
例子
const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');
const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr");
var decrypt = CryptoJS.AES.decrypt({ciphertext: crypted}, cryptkey, {
iv: CryptoJS.enc.Hex.parse('00000000000000000000000000000000'),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
console.log(decrypt.toString(CryptoJS.enc.Utf8));
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
正如 Matt 正确指出的那样,如果密文编码为 Base64,CryptoJS 可以为您进行密文解码:
const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');
const crypted = "8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr";
var decrypt = CryptoJS.AES.decrypt(crypted, cryptkey, {
iv: CryptoJS.enc.Hex.parse('00000000000000000000000000000000'),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
console.log(decrypt.toString(CryptoJS.enc.Utf8));
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
安全考虑:
IV 必须是不可预测的(读作:随机)。不要使用静态 IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前发送相同消息前缀的时间。 IV 不是 secret 的,因此您可以将它与密文一起发送。通常,它只是简单地添加到密文之前并在解密之前被切掉。
key 应该从所有可能的字节中随机选择,因为由 ASCII 字符组成的 key 比由所有可用字节组成的 key 更容易暴力破解。
最好对您的密文进行身份验证,这样像 padding oracle attack 这样的攻击就不可能发生。这可以通过 GCM 或 EAX 等经过身份验证的模式或 encrypt-then-MAC 方案来完成。
如果您只使用对称加密,您需要在服务器和客户端使用完全相同的 key 。如果您将加密 key 从服务器发送到客户端或以其他方式发送,您需要加密您的对称加密 key 。最简单的方法是使用 TLS。如果您使用 TLS,那么数据和 key 都会被加密,因此您不需要自己加密。这不提供任何安全性,只是有点混淆。你应该阅读:https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
关于javascript - CryptoJS AES 无法解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42989586/