CryptoJS AES无法解密

ale*_*rov 1 javascript encryption cryptography aes

我需要解密使用AES加密的传入请求,我尝试使用共享示例,但找不到正确的参数集

  • 加密AES / CBC / PKCS5填充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);
Run Code Online (Sandbox Code Playgroud)

每次我得到空字符串。我在哪里失败?

------更新-----

带有注释的新版本仍然无法正常工作

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
});
Run Code Online (Sandbox Code Playgroud)

Art*_* B. 5

您必须首先解析UTF-8密钥:

const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');
Run Code Online (Sandbox Code Playgroud)

如果您不这样做,则CryptoJS将假定它是一个密码,并从中得出实际的密钥。

正如马尔滕也指出的那样...

密文还必须从Base64解码:

const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr");
Run Code Online (Sandbox Code Playgroud)

请注意,解密器需要一个CipherParams对象,您可以通过传递{ciphertext: crypted}decrypt函数来模拟该对象。或者,您可以依靠CryptoJS从Base64解码密文,然后按原样传递该字符串。

AES-CBC的IV必须为16个字节长,如果编码为十六进制,则为32个字符:

CryptoJS.enc.Hex.parse('00000000000000000000000000000000')
Run Code Online (Sandbox Code Playgroud)

例子

const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');
Run Code Online (Sandbox Code Playgroud)
const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr");
Run Code Online (Sandbox Code Playgroud)

正如Matt正确指出的,如果密文编码为Base64,则CryptoJS可以为您进行密文解码:

CryptoJS.enc.Hex.parse('00000000000000000000000000000000')
Run Code Online (Sandbox Code Playgroud)
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));
Run Code Online (Sandbox Code Playgroud)


安全注意事项:

IV必须是不可预测的(读取:随机)。不要使用静态IV,因为这会使密码具有确定性,因此在语义上也不安全。观察密文的攻击者可以确定以前何时发送相同的消息前缀。IV不是秘密的,因此您可以将其与密文一起发送。通常,它只是简单地加在密文之前,并在解密之前将其切开。

应该从所有可能的字节中随机选择一个密钥,因为由ASCII字符组成的密钥比由所有可用字节组成的密钥更容易被暴力破解。

最好对您的密文进行身份验证,这样就不可能进行像填充oracle攻击之类的攻击。这可以通过GCM或EAX之类的经过身份验证的模式来完成,也可以通过“ 加密-然后-MAC”方案来完成。

如果仅使用对称加密,则服务器和客户端需要完全相同的密钥。如果您将加密密钥从服务器发送到客户端或以其他方式发送,则需要对对称加密密钥进行加密。最简单的方法是使用TLS。如果使用TLS,则数据和密钥都会被加密,因此您无需自己对其进行加密。这没有提供任何安全性,只是有点混淆。您应该阅读:https : //www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/

  • @aleks.n.fedorov 默认情况下,CryptoJS 将密文视为 Base64 编码并为您解码,因此您不需要自己解码。 (2认同)