CryptoJS AES无法解密

时间:2017-03-24 00:55:54

标签: javascript encryption cryptography aes

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

  • 加密:AES / CBC / PKCS5Padding AES / CBC / PKCS5
  • 初始化向量:longbyte数组,长度为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
});

3 个答案:

答案 0 :(得分:4)

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

W

如果你不这样做,CryptoJS会认为它是一个密码并从中获取实际的密钥。

正如Maarten所指出的......

密文也必须从Base64解码:

const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');

请注意,解密器需要一个const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr"); 对象,您可以通过将CipherParams传递给{ciphertext: crypted}函数来模拟该对象。或者,你可以依靠CryptoJS来解码Base64中的密文,你按原样传入该字符串。

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

decrypt

实施例



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));




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



<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
&#13;
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));
&#13;
&#13;
&#13;

安全注意事项:

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

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

最好对您的密文进行身份验证,以便像padding oracle attack这样的攻击是不可能的。这可以使用经过身份验证的模式(如GCM或EAX)或encrypt-then-MAC方案来完成。

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

答案 1 :(得分:0)

您忘记了对crypted中的密文进行64解码(我猜您必须使用atob()来执行此操作)。你的IV也太小了,十六进制每个字节需要两个十六进制数字。

答案 2 :(得分:0)

这对我有用,使用 enc 而不仅仅是 UTF8

const { AES, enc } = require('crypto-js')
const { decrypt, encrypt } = AES


const message = "Hi my friend"
const messageEncrypt = "oPVu8Dd8ERPIAWr+7rQzIQ=="
const key= "key123456"
const aesDecrypt = decrypt(messageEncrypt,key).toString(enc.Utf8)
console.log(aesDecrypt) // Hi my friend