如何通过javascrypt(不是Node.js)解密AES 256 CBC?

时间:2019-12-25 02:31:04

标签: javascript encryption aes

如何在 AES 256 CBC 模式下使用密钥dIwykUwOomuWcdw/QX/Aig==和iv ds8am3wys3pd75nf0ggtvajw2k3uny92解密加密的字符串,例如jm8lgqa3j1d0ajus,如下图所示,仅使用javascript (不是Node.js)。我曾经尝试使用CryptoJs库,但结果却不像我预期的那样。

enter image description here

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/pbkdf2.js"></script>
<script>
    var str = 'dIwykUwOomuWcdw/QX/Aig==';
    var key = 'ds8am3wys3pd75nf0ggtvajw2k3uny92';
    var iv  = 'jm8lgqa3j1d0ajus';

    var encrypted = CryptoJS.AES.encrypt("2730007809303", key, { iv: iv });
    var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv});
    var base64_str = decrypted.toString(CryptoJS.enc.Base64);
    console.log(atob(base64_str))
</script>

顺便问一下,如何将输入字符串dIwykUwOomuWcdw/QX/Aig==转换为上方的encrypted对象?

1 个答案:

答案 0 :(得分:0)

您的代码段几乎是正确的。但是,密钥必须 not 不能作为字符串传递,否则CryptoJS会将其解释为密码短语并从中生成{em> actual 密钥和[1] IV,并带有顺便说一句不安全的算法。相反,密钥和IV必须作为WordArray传递,使用编码器[2]可以轻松实现。由于在此示例中key和IV是Utf8字符串,因此必须使用Utf8编码器进行解析。然后,您将获得所需的网页密文。请注意,encrypt返回一个CipherParams对象,该对象封装了其他数据[3]中的密文。此外,您不需要Base64弯路,而应将解码后的数据直接解码为UTF8字符串:

var key = CryptoJS.enc.Utf8.parse('ds8am3wys3pd75nf0ggtvajw2k3uny92');     // Use Utf8-Encoder. 
var iv  = CryptoJS.enc.Utf8.parse('jm8lgqa3j1d0ajus');                     // Use Utf8-Encoder

var encryptedCP = CryptoJS.AES.encrypt("2730007809303", key, { iv: iv });
var decryptedWA = CryptoJS.AES.decrypt(encryptedCP, key, { iv: iv});

var encryptedBase64 = encryptedCP.toString();                              // Short for: encryptedCP.ciphertext.toString(CryptoJS.enc.Base64);
var decryptedUtf8 = decryptedWA.toString(CryptoJS.enc.Utf8);               // Avoid the Base64 detour.
                                                                           // Alternatively: CryptoJS.enc.Utf8.stringify(decryptedWA);  
console.log("Ciphertext (Base64)  : " + encryptedBase64)
console.log("Decrypted data (Utf8): " + decryptedUtf8); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>

请注意,隐式使用了CBC模式和PKCS7填充,它们是CryptoJS [4]的默认参数,因此没有必要明确指定它们。

更新

如果密文是字符串或WordArray,则必须从中创建一个CipherParams对象,因为decrypt方法需要这种类型的对象{{3} }。 CipherParams对象封装的所有数据的全部都可以很容易地从其定义[5]中获取。在当前情况下,至少必须将密文指定为WordArray。可以选择指定格式化程序,用于确定toString()的格式化策略(如果使用):

var key = CryptoJS.enc.Utf8.parse('ds8am3wys3pd75nf0ggtvajw2k3uny92');     // Use Utf8-Encoder. 
var iv  = CryptoJS.enc.Utf8.parse('jm8lgqa3j1d0ajus');                     // Use Utf8-Encoder

var ciphertext = CryptoJS.enc.Base64.parse('dIwykUwOomuWcdw/QX/Aig==');    // Use Base64-Encoder.       
var encryptedCP = CryptoJS.lib.CipherParams.create({
    ciphertext: ciphertext,
    formatter: CryptoJS.format.OpenSSL                                     // Optional, but required for encryptedCP.toString() 
});
var decryptedWA = CryptoJS.AES.decrypt(encryptedCP, key, { iv: iv});

var encryptedBase64 = encryptedCP.toString();                              // Short for: encryptedCP.ciphertext.toString(CryptoJS.enc.Base64);
var decryptedUtf8 = decryptedWA.toString(CryptoJS.enc.Utf8);               // Avoid the Base64 detour.
                                                                           // Alternatively: CryptoJS.enc.Utf8.stringify(decryptedWA);  
console.log("Ciphertext (Base64)  : " + encryptedBase64)
console.log("Decrypted data (Utf8): " + decryptedUtf8);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>