在js逆向遇到AES,CBC模式加密并没有带iv而是每次随机生成的iv,python带的库没有相关实现,不能实现解密,故记录一下python相关实现:

import os

from Crypto.Cipher import AES
import base64
import hashlib


def encrypt_aes(plaintext, password):
    # 生成随机盐
    salt = os.urandom(8)

    # 根据密码和盐生成密钥和 IV
    key_iv = b""
    last_hash = b""
    while len(key_iv) < 48:  # 32 字节密钥 + 16 字节 IV
        last_hash = hashlib.md5(last_hash + password.encode() + salt).digest()
        key_iv += last_hash

    key = key_iv[:32]  # 前 32 字节是密钥
    iv = key_iv[32:48]  # 后 16 字节是 IV

    # 初始化 AES 加密器
    cipher = AES.new(key, AES.MODE_CBC, iv)

    # PKCS7 填充
    padding_len = 16 - len(plaintext) % 16
    padded_plaintext = plaintext + chr(padding_len) * padding_len

    # 加密数据
    encrypted_data = cipher.encrypt(padded_plaintext.encode())

    # 输出格式为 Salted__ + 盐 + 密文
    ciphertext = b"Salted__" + salt + encrypted_data

    # 使用 Base64 编码返回
    return base64.b64encode(ciphertext).decode('utf-8')


def decrypt_aes(ciphertext_base64, password):
    # 解码 Base64 密文
    ciphertext = base64.b64decode(ciphertext_base64)

    # 检查是否以 "Salted__" 开头
    if not ciphertext.startswith(b"Salted__"):
        raise ValueError("Invalid ciphertext format")

    # 提取盐 (salt)
    salt = ciphertext[8:16]

    # 提取密文部分
    encrypted_data = ciphertext[16:]

    # 根据密码和盐生成密钥和 IV (Key 和 IV derivation)
    key_iv = b""
    last_hash = b""
    while len(key_iv) < 48:  # 32 字节密钥 + 16 字节 IV
        last_hash = hashlib.md5(last_hash + password.encode() + salt).digest()
        key_iv += last_hash

    key = key_iv[:32]  # 前 32 字节是密钥
    iv = key_iv[32:48]  # 后 16 字节是 IV

    # 初始化 AES 解密器
    cipher = AES.new(key, AES.MODE_CBC, iv)

    # 解密数据
    decrypted_data = cipher.decrypt(encrypted_data)

    # 去除 PKCS7 填充
    padding_len = decrypted_data[-1]
    if padding_len > 16:  # 填充长度不可能超过块大小
        raise ValueError("Invalid padding")
    decrypted_data = decrypted_data[:-padding_len]

    return decrypted_data.decode('utf-8')


if __name__ == '__main__':
    # 测试
    password = "dRgUkXp2r5u8x/A?D(G+KbPeShVmYq3t"

    encrypted = encrypt_aes("{1:2}", password)
    dencrypted = decrypt_aes(encrypted, password)
    print(encrypted)
    print(dencrypted)