javascript 如何使用crypto-js解密AES ECB

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14327136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 21:18:56  来源:igfitidea点击:

How to decrypt AES ECB using crypto-js

javascriptecb

提问by wingnut

I am trying to send encrypted data from flash (client side) to javascript (running as jscript in asp) on the server side.

我正在尝试将加密数据从闪存(客户端)发送到服务器端的 javascript(在 asp 中作为 jscript 运行)。

There are several javascript Aes libraries, but they are virtually undocumented. I'm trying with crypto-js, but cant get the code to work. The below example generates an empty output, it should generate "6bc1bee22e409f96e93d7e117393172a".

有几个 javascript Aes 库,但它们几乎没有记录。我正在尝试使用 crypto-js,但无法使代码正常工作。下面的示例生成一个空输出,它应该生成“6bc1bee22e409f96e93d7e117393172a”。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-ecb.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script>
<script>
    var key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c');
    var data = CryptoJS.enc.Hex.parse('3ad77bb40d7a3660a89ecaf32466ef97');
    var decrypted3 = CryptoJS.AES.decrypt(data, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
    document.write("<br /> dec3: " + decrypted3.toString());
</script>
</body>
</html>

I took a documented working key and encrypted data from http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors

我从http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors 获取了记录的工作密钥和加密数据

I am using ECB because its the only version which doesn't require an IV or salt, as the server wont know the IV or salt used on the client, so would not be able to decrypt the data.

我使用 ECB 是因为它是唯一不需要 IV 或盐的版本,因为服务器不知道客户端使用的 IV 或盐,因此无法解密数据。

Does anyone have any clue why the above fails to decrypt the data, or know where any documentation is?

有没有人知道为什么上述无法解密数据,或者知道任何文档在哪里?

Update: After some hours of trial and error, I came up with a combination which produces the output: 7c121d95a84573b6120ada2ffff1ce3118561eba40555c0b However, this is still incorrect. The change made to produce this was:

更新:经过几个小时的反复试验,我想出了一个产生输出的组合:7c121d95a84573b6120ada2ffff1ce3118561eba40555c0b 但是,这仍然是不正确的。为产生这个所做的改变是:

 var decrypted3 = CryptoJS.AES.decrypt('3ad77bb40d7a3660a89ecaf32466ef97', key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });

I.e. I passed the data in as a string of hex, which cant be right, but does produce output at least.

即我将数据作为十六进制字符串传入,这不可能是正确的,但至少会产生输出。

The next problem will be padding issues. On the client I am using AS3 hurlant libraries, which only offer two padding strategies: NONE and PKCS#5. In crypto-js, the available strategies are:

下一个问题将是填充问题。在客户端,我使用 AS3 hurrant 库,它只提供两种填充策略:NONE 和 PKCS#5。在crypto-js中,可用的策略是:

Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
NoPadding 

Does this mean there will be no chance to every decrypt data between the two libraries? Before I have had to write my own padding hacks (between AS3 and java), to add or remove trailing data, but this took days of trial and error with binary data - there must be an easier way to send a single encrypted string from client to server.

这是否意味着没有机会在两个库之间解密数据?在我不得不编写自己的填充技巧(在 AS3 和 java 之间)来添加或删除尾随数据之前,但这需要数天的二进制数据试验和错误 - 必须有一种更简单的方法来从客户端发送单个加密字符串到服务器。

SSL is not an option as the client user can simply use Charles proxy or similar to see and tamper with the unencrypted data.

SSL 不是一种选择,因为客户端用户可以简单地使用 Charles 代理或类似工具来查看和篡改未加密的数据。

回答by frederickf

The example below returns the desired output using AES and ECB.

下面的示例使用 AES 和 ECB 返回所需的输出。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
    <script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
    <script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-ecb.js"></script>
    <script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script>


    <script>
        var encrypted = '3ad77bb40d7a3660a89ecaf32466ef97',
            key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c'),
            cipherParams = CryptoJS.lib.CipherParams.create({
                ciphertext: CryptoJS.enc.Hex.parse(encrypted)         
            });

        var decrypted3 = CryptoJS.AES.decrypt(cipherParams, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
        document.write("<br /> dec3: " + CryptoJS.enc.Hex.stringify(decrypted3));
    </script>
</body>
</html>

The only real differences is creating a cypherParams object using CryptoJS.lib.CipherParams.create(). According to the official docsa cypherParams object "gives you access to all the parameters used during encryption" including key, iv, salt and the original cypherText. Basically all the info needed to decrypt it. In our case we needed to convert the encrypted data to cypherParam with only the cypherText property. Incidentally the cypherParam can be stringified using standard formats, which is how it is communicated to other systems.

唯一真正的区别是使用 CryptoJS.lib.CipherParams.create() 创建一个 cypherParams 对象。根据官方文档,cypherParams 对象“使您可以访问加密期间使用的所有参数”,包括密钥、iv、salt 和原始密码文本。基本上解密它所需的所有信息。在我们的例子中,我们只需要使用 cypherText 属性将加密数据转换为 cypherParam。顺便提一下,cypherParam 可以使用标准格式进行字符串化,这就是它与其他系统通信的方式。

Regarding the padding, as I understandit Pkcs7 is an extension of Pkcs5 and should work for any cypher created using Pkcs5. When I tried the code sample above without the NoPadding option (defaulting to Pkcs7) it didn't work, but I can't tell what was used in creating that encrypted data. At least that AES Test Vectors page you linked to doesn't tell us.

关于填充,据我所知,Pkcs7 是 Pkcs5 的扩展,应该适用于使用 Pkcs5 创建的任何密码。当我在没有 NoPadding 选项(默认为 Pkcs7)的情况下尝试上面的代码示例时,它不起作用,但我不知道在创建加密数据时使用了什么。至少您链接到的 AES 测试向量页面没有告诉我们。

回答by wingnut

Gave up with ECB, tried various permutations with CBC, and got one to work. It also seems that it is OK to send the IV in plain text from client to server.

放弃了 ECB,尝试了与 CBC 的各种排列,并获得了一个工作。似乎也可以将 IV 以纯文本形式从客户端发送到服务器。

Here is the version which correctly outputs "6bc1bee22e409f96e93d7e117393172a". Shock.

这是正确输出“6bc1bee22e409f96e93d7e117393172a”的版本。震惊。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<!--script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-cbc.js"></script-->
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script>
<script>
    var key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c');
    var iv = CryptoJS.enc.Hex.parse('000102030405060708090A0B0C0D0E0F');
    var data = CryptoJS.enc.Hex.parse('7649abac8119b246cee98e9b12e9197d');      

    var encrypted = {};
    encrypted.key=key;
    encrypted.iv=iv;
    encrypted.ciphertext = data;

    var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, padding: CryptoJS.pad.NoPadding });

    document.write("<br /> dec3: " + CryptoJS.enc.Hex.stringify(decrypted));
</script>
</body>
</html>

回答by Sushant Dahiya

This a working and updated answer, with updated CDN links and a function that converts the resultant decrypted data into plaintext.

这是一个有效且更新的答案,具有更新的 CDN 链接和一个将生成的解密数据转换为明文的功能。

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    </head>
    <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/cipher-core.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/mode-ecb.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/pad-nopadding.js"></script>


    <script>
    var encrypted = 'B655564D4428C56E7F9E44D81770CFDBC3FB0FCEA8FFDF7CC936FFE6C7A595A0FE085FAA65796C4C24D0862FAF56CAA1880DCD281A891DD1E999F953F2B669291B41B486E0FEC5E11BE7B7348703665081E4FF79F815C35803506468548F3C5EE13B5783A0E22D91E08CB1897E4D135DA8C4E650A1D51FFDDD210311A0835FD8E8EE08CC968F8A0B0EF811554872A093',
    key = CryptoJS.enc.Hex.parse('844AF9144552AFAE26A9C45FD5882718'),
    cipherParams = CryptoJS.lib.CipherParams.create({
        ciphertext: CryptoJS.enc.Hex.parse(encrypted)
    });

    var decrypted3 = CryptoJS.AES.decrypt(cipherParams, key, 
    {mode: CryptoJS.mode.ECB, 
        padding: CryptoJS.pad.NoPadding });
       document.write("<br />" + hex2a(CryptoJS.enc.Hex.stringify(decrypted3)));
    function hex2a(hexx) {
    var hex = hexx.toString();//force conversion
    var str = '';
    for (var i = 0; i < hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    return str;
}
</script>
</body>
</html>