javascript - CryptoJS AES 无法解密

标签 javascript encryption cryptography aes

我需要解密使用 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/

相关文章:

c# - 对称加密加密很多小块

node.js - 使用模块 'crypto' 对十六进制数据进行 NodeJS DES ECB 加密

javascript - 检查对象数组 key 是否为空并拼接它

javascript - 如何使用 knex 从 SQL 表中选择行值连续的情况?

javascript - 如何阻止用户在 Angular 的文本框中输入 URL

linux - encfs解密,文件名编码 'nameio/block' 4.0.0不支持

javascript - 向 JS 对象添加额外的值

ios - 在 iOS 上使用 Openssl 的 CMS 加密问题

c++ - 为什么我会收到类型不匹配错误 Crypto++ AES

node.js - 一次成功加密和解密后,Nodejs Crypto 解密失败