CryptoJS AES无法解密 [英] CryptoJS AES Unable to decrypt

查看:83
本文介绍了CryptoJS 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 crypto = CryptoJS.AES.decrypt(crypted,cryptkey,{iv:CryptoJS.enc.Hex.parse('0000000000000000'),模式:CryptoJS.mode.CBC,填充:CryptoJS.pad.Pkcs7});var ddd = crypto.toString(CryptoJS.enc.Utf8);console.log(ddd); 

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

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

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

  const cryptkey = CryptoJS.enc.Utf8.parse('1234567890123456');const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP + VuJGePqIMv1uSaVErr");var crypto = CryptoJS.AES.decrypt(crypted,cryptkey,{iv:CryptoJS.enc.Hex.parse('00000000000000000000000000000000'),模式:CryptoJS.mode.CBC,填充:CryptoJS.pad.Pkcs7}); 

解决方案

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

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

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

正如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 crypto = CryptoJS.AES.decrypt({ciphertext:crypted},cryptkey,{iv:CryptoJS.enc.Hex.parse('00000000000000000000000000000000'),模式:CryptoJS.mode.CBC,填充: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 crypto = CryptoJS.AES.decrypt(crypted,cryptkey,{iv:CryptoJS.enc.Hex.parse('00000000000000000000000000000000'),模式:CryptoJS.mode.CBC,填充: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不是秘密的,因此您可以将其与密文一起发送.通常,它只是简单地放在密文的前面,然后在解密之前将其切掉.

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

最好对您的密文进行身份验证,以免像填充oracle攻击这样的攻击.可以使用GCM或EAX等经过身份验证的模式,也可以使用 encrypt-then-MAC 方案来完成.>

如果仅使用对称加密,则在服务器和客户端上需要完全相同的密钥.如果您将加密密钥从服务器发送到客户端或以其他方式发送,则需要对对称加密密钥进行加密.最简单的方法是使用TLS.如果使用TLS,则数据和密钥都会被加密,因此您无需自己对其进行加密.这没有提供任何安全性,只是有点混淆.您应该阅读:

Every time I am getting empty string. Where do I fail?

------ UPDATE -----

New version with applied comments, still does not work

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

解决方案

You would have to parse the UTF-8 key first:

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

If you don't do that CryptoJS will assume it is a password and derive the actual key from that.

As Maarten also pointed out...

The ciphertext also must be decoded from Base64:

const crypted = CryptoJS.enc.Base64.parse("8Z3dZzqn05FmiuBLowExK0CAbs4TY2GorC2dDPVlsn/tP+VuJGePqIMv1uSaVErr");

Note that the decryptor expects a CipherParams object, which you can simulate by passing {ciphertext: crypted} to the decrypt function. Alternatively, you can rely on CryptoJS to decode the ciphertext from Base64, you pass in that string as-is.

The IV must be 16 bytes long for AES-CBC which are 32 characters if encoded as Hex:

CryptoJS.enc.Hex.parse('00000000000000000000000000000000')


Examples

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>

As Matt correctly noted, CryptoJS can do the ciphertext decoding for you if the ciphertext is encoded as Base64:

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>


Security considerations:

The IV must be unpredictable (read: random). Don't use a static IV, because that makes the cipher deterministic and therefore not semantically secure. An attacker who observes ciphertexts can determine when the same message prefix was sent before. The IV is not secret, so you can send it along with the ciphertext. Usually, it is simply prepended to the ciphertext and sliced off before decryption.

A key should be randomly chosen from all possible bytes, because a key consisting of ASCII characters is much easier to brute-force than a key consisting of all available bytes.

It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme.

If you're using only symmetric encryption you need the exact same key at the server and the client. If you send the encryption key from the server to the client or the other way around you need to encrypt your symmetric encryption key. The easiest way to do this would be to use TLS. If you use TLS, then the data as well as key are encrypted, so you don't need to encrypt it yourself. This doesn't provide any security, just a little bit of obfuscation. You should read: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/

这篇关于CryptoJS AES无法解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆