Python 模拟 NodeJS的AES加密和解密

我需要用Python Requests 来爬取数据,但是数据库请求被加密了,加密模式是“aes-128-ecb”,以下是NodeJS的加密和解密结果:

var key = "1101101101100000"
var enc_str = "test_str"

var crypto = require("crypto")
var cipher = crypto.createCipher("aes-128-ecb", key)
var crypted = cipher.update(enc_str, "utf-8", "hex")
crypted += cipher.final("hex")
console.log(crypted)

var d_cipher = crypto.createDecipher("aes-128-ecb", key)
decrypted = d_cipher.update(crypted, "hex", "utf-8")
decrypted += d_cipher.final("utf-8")
console.log(decrypted)

结果:

'0298a0c9502a3277d065032d66ebb8b7'
'test_str'

我尝试用Python 的 Crypto 来模拟加密和解密,然而得到的结果不一样,以下是Python的结果:

"""aes-128-ecb"""
from Crypto.Cipher import AES
import binascii


class Encryptor(object):

    def __init__(self, key, block_size):
        self.key = key
        self.block_size = block_size
        self.en_code = 'utf-8'
        self.cipher = AES.new(key.encode(self.en_code), AES.MODE_ECB)

    def encrypt_str(self, enc_str):
        padded_data = self.pad(enc_str.encode(self.en_code))
        encrypted = self.cipher.encrypt(padded_data)
        return binascii.b2a_hex(encrypted).decode(self.en_code)

    def decrypt_str(self, dec_str):
        decrypted = self.cipher.decrypt(binascii.a2b_hex(dec_str))
        return self.unpad(decrypted).decode(self.en_code)

    def pad(self, pad_str):
        padding_size = self.block_size - len(pad_str) % self.block_size
        padded_data = pad_str + padding_size * chr(padding_size).encode(self.en_code)
        return padded_data

    def unpad(self, unpad_str):
        padding_size = unpad_str[-1]
        return unpad_str[:-padding_size]


if __name__ == '__main__':
    key = '1101101101100000'
    enc_str = 'test_str'
    encryptor = Encryptor(key, 16)
    enc_data = encryptor.encrypt_str(enc_str)
    print(enc_data)
    dec_data = encryptor.decrypt_str(enc_data)
    print(dec_data)

结果:

'48ef7b31d0874147929ae99cd38cf5d0'
'test_str'

想请问如何用 Python 模拟 NodeJS 的加密和解密,得到同样的结果

自己解决了
详见:


需要把key通过下面的函数转换,然后再使用:

import hashlib

def evp_bytes_to_key(key_size: int, block_size: int, salt: bytes, data: bytes, md=hashlib.md5, count=1):
    """
    Usage:
        key, iv = evp_bytes_to_key(
            16,  # 128 bits
            Crypto.Cipher.AES.block_size,
            hashlib.sha256,
            salt,
            password.encode('utf-8'),
            )
    See:
        https://github.com/openssl/openssl/blob/6f0ac0e2f27d9240516edb9a23b7863e7ad02898/crypto/evp/evp_key.c#L74
    """
    assert data
    assert salt == b'' or len(salt) == 8

    md_buf = b''
    key = b''
    iv = b''

    addmd = 0

    while key_size > len(key) or block_size > len(iv):
        c = md()
        if addmd:
            c.update(md_buf)
        addmd += 1
        c.update(data)
        c.update(salt)
        md_buf = c.digest()
        for i in range(1, count):
            md_buf = md(md_buf)

        md_buf2 = md_buf

        if key_size > len(key):
            key, md_buf2 = key + md_buf2[:key_size - len(key)], md_buf2[key_size - len(key):]

        if block_size > len(iv):
            iv, md_buf2 = iv + md_buf2[:block_size - len(iv)], md_buf2[block_size - len(iv):]

    return key, iv