如何用Python解密用Javascript加密的数据?

时间:2016-07-20 13:58:20

标签: javascript python aes pycrypto cryptojs

我有一个类似

的页面的javascript代码
    var link = '{"ct":"AAQz1rUDqp849MRxu0tqGRGvPcLzVG24xa5zbYxpwVHH6Z2p95xPPzNhMIRMcaTPvijE71RQU1X3cQhtnXdRScA6UBiLWNs9vMul2gldnMTpT92sDYHl+hKBGy2dR22Un7ElToipSqeqRrwhEK8T9ROMChrBw8i7JOICpOYoVhqDB72BH2RG\/PqjRqsKittES5BVhTTY9cs+zQI0rM+FQA62bVCL57P3RD+E+aWJJLjUvoXBqct6Jc5W7li9mk9udgn9rPKkCbXSCvwIxcWS5C1kw4uSO7y0IlovaTWLAIw5nY0l4REjbC1wPWrtxDWLlr8J+\/sQdDF+P61VHz6yiC+w56QLDjVwz4kBl3r3uP\/VZ7kUuLwWHSHnbmmXv31f","iv":"feae762ac889376169708872d9676319","s":"9b2328e8a4ee2717"}';
    var msg = "f12c8b59265dc1e898135211cc30be49";    
    var finalUrl = JSON.parse(CryptoJS.AES.decrypt(link, msg, {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));

我认为ct是加密的msg,s是Salt,iv是iv

我正在尝试用python解码finalUrl。

    AES=AESDecrypter()
    decryptor = AES.new(s, AES.MODE_CBC, IV=iv)
    dec = decryptor.decrypt(ct)

我知道它不起作用,因为我无法计算如何使用

    var msg = "f12c8b59265dc1e898135211cc30be49" in Python.

还认为CryptoJSAesJson可能有一些额外的功能。 有人请告诉我如何用Python在这里给出的数据检索finalUrl。 任何建议都非常感谢。为我糟糕的编码知识道歉。

1 个答案:

答案 0 :(得分:1)

实际的 AES 密钥是通过以下过程派生的(派生自 https://stackoverflow.com/a/27582253/5722339):

  1. 所需的库。

    import base64;
    import hashlib;
    from Crypto.Cipher import AES;
    
  2. 将提供的输入从十六进制或 base64 字符串解码为原始字节。

    ct = base64.b64decode("AAQz1rUDqp849MRx ... bmmXv31f");
    iv = bytes.fromhex("feae762ac889376169708872d9676319");
    salt = bytes.fromhex("9b2328e8a4ee2717");
    
    # In your case, the pass phrase is NOT a hex-encoded byte array.
    #  It is directly used as bytes.
    pass_phrase = b"f12c8b59265dc1e898135211cc30be49";
    
  3. 使用 MD5 摘要对密码短语和盐进行哈希处理,以导出密钥的前 128 位(16 字节)。

    md = hashlib.md5();
    md.update(pass_phrase);
    md.update(salt);
    cache0 = md.digest();
    
  4. md = hashlib.md5();
    md.update(cache0);
    md.update(pass_phrase);
    md.update(salt);
    cache1 = md.digest();
    
  5. 连接两个字节数组以获取 256 位 AES 密钥。

    key = cache0 + cache1;
    
  6. 最后,使用 256 位 AES 和 CBC 模式解密密文。

    cipher = AES.new(key, AES.MODE_CBC, iv);
    result = cipher.decrypt(ct);
    

    解密后的数据现在作为字节数组存储在 result 中。

请注意,虽然您的示例输入中的密文 ct 是 base64 编码的,并且 saltiv 都是十六进制编码的,但密码短语不是十六进制编码的(尽管看起来是这样)。

此外,您可能需要在使用之前先取消填充输出。可以通过使用 lambda 来实现 un-pad 功能:(来自 https://stackoverflow.com/a/12525165/5722339 的解决方案)

unpad = lambda s : s[:-ord(s[len(s)-1:])];

样本输入的输出是: http:\/\/pmd.dittotv3.com.edgesuite.net\/draco\/shows\/Zee_Bangla\/Dweep_Jwele_Jai\/July\/19072016\/Webisode\/Dweep_Jwele_Jai_Webisode_19072016_100.mp4?key1=ozee.com&hdnea=st=1469018324~exp=1469020124~acl=%2F%2A~hmac=07e8cf2b49f51899f60b129f3a99eb792f45e779fbdae94d4a70215398fc590d