【问题标题】:How to decrypt AES ECB using crypto-js如何使用 crypto-js 解密 AES ECB
【发布时间】:2012-12-28 22:13:21
【问题描述】:

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

有几个 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>

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

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

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

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

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

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

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

Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
NoPadding 

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

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

【问题讨论】:

  • 我正在尝试同样的事情,它似乎不起作用。我正在使用 ECB 使用 Crypto.JS 进行加密,然后尝试使用带有 ECB 的 CryptoJS 解密 CryptoJS 产生的相同哈希值,但它不起作用。我确实设法获得了输出,但这是错误的。我觉得图书馆有些东西不能正常工作。唯一有效的方法是在加密到解密器时提供 CryptoJS 返回给您的整个对象。这很愚蠢,因为我想把它发送给其他人解密。
  • 不要使用 ECB 模式,它不安全,请参阅ECB mode,向下滚动到企鹅。而是使用随机 IV 的 CBC 模式,只需在加密数据前加上 IV 以用于解密。

标签: javascript ecb


【解决方案1】:

下面的示例使用 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>

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

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

【讨论】:

    【解决方案2】:

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

    这是正确输出“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>
    

    【讨论】:

    • 这个答案对我来说非常有效。如果您想将解密的字节视为字符串,请使用: document.write("
      解密文本:" + decrypted.toString(CryptoJS.enc.Utf8) );
    • 能展示一下加密数据的js代码吗?我也在为解密而苦苦挣扎,无法使您的代码正常工作。也许查看加密的数据可以帮助我。
    【解决方案3】:

    这是一个有效且更新的答案,具有更新的 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-06
      • 2022-09-27
      • 2022-11-20
      • 1970-01-01
      • 1970-01-01
      • 2020-01-31
      • 1970-01-01
      • 2013-08-16
      相关资源
      最近更新 更多