You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyCryptodome解密AES-128 ECB文件无法识别正确密钥如何处理

核心问题排查

首先你现有代码存在3个典型错误,是无有效输出的主要原因:

  1. 密钥长度不匹配:AES-128要求密钥长度为16字节,你用的32字符密钥如果是十六进制格式,直接用str.encode()转换会得到32字节(符合AES-256的密钥长度),和题目要求的AES-128不匹配,这是最常见的踩坑点。
  2. 未处理填充:你自己测试加密时手动加了PKCS7填充,但解密目标文件时没有去掉解密结果末尾的填充字节,就算解密正确,填充字节也会导致文本解码失败、文件格式识别错误。
  3. 判断逻辑错误:遍历字符编码仅适用于原文件是纯文本的场景,如果原文件是压缩包、图片、办公文档等二进制格式,本身就无法用字符编码解码,自然不会有任何输出。

解决步骤

第一步:修正密钥处理逻辑

如果候选密钥是32位十六进制字符串(比如202cb962ac59075b964b07152d234b70这类格式),用bytes.fromhex(key)代替str.encode(key)转换密钥,得到的16字节刚好符合AES-128的密钥要求。

第二步:添加PKCS7去填充逻辑

解密完成后先去掉末尾的填充字节再做后续判断:

def pkcs7_unpad(data):
    pad_len = data[-1]
    if pad_len < 1 or pad_len > 16:
        raise ValueError("无效填充长度")
    return data[:-pad_len]

第三步:用文件魔数判断解密有效性

绝大多数正规格式的文件都有固定的头部标识(魔数),不需要解码,直接匹配解密结果的前几个字节就能判断是否合法,常见魔数参考:

  • b'PK':ZIP压缩包、docx/xlsx文档、APK安装包等
  • b'\xff\xd8':JPG图片
  • b'\x89PNG':PNG图片
  • b'%PDF':PDF文档
  • b'MZ':Windows EXE可执行文件
  • b'\x7fELF':Linux ELF可执行文件

如果是纯文本,判断可打印字符(ASCII 32~126、换行、回车、制表符)占比超过90%即可判定为有效。


修正后参考代码

from Crypto.Cipher import AES

# 可自行补充更多魔数
MAGIC_NUMBERS = [
    b'PK', b'\xff\xd8', b'\x89PNG', b'%PDF', b'MZ', b'\x7fELF', b'Rar'
]

def pkcs7_unpad(data):
    pad_len = data[-1]
    if pad_len < 1 or pad_len > 16:
        raise ValueError("无效填充长度")
    return data[:-pad_len]

keys = [你的32位候选密钥列表]

with open("file.aes", "rb") as f:
    ciphertext = f.read()

for key in keys:
    try:
        # 十六进制密钥转换为16字节二进制,普通字符串密钥改为key.encode()即可
        key_bytes = bytes.fromhex(key)
        if len(key_bytes) != 16:
            continue
        cipher = AES.new(key_bytes, AES.MODE_ECB)
        decrypted = cipher.decrypt(ciphertext)
        plain_data = pkcs7_unpad(decrypted)
        # 匹配二进制文件魔数
        for magic in MAGIC_NUMBERS:
            if plain_data.startswith(magic):
                print(f"找到有效密钥:{key},匹配文件魔数:{magic}")
                # 保存解密结果
                with open(f"decrypted_{key}.bin", "wb") as out_f:
                    out_f.write(plain_data)
                break
        # 匹配纯文本
        printable_cnt = sum(1 for b in plain_data if 32 <= b <= 126 or b in (b'\n', b'\r', b'\t'))
        if printable_cnt / len(plain_data) > 0.9:
            print(f"找到疑似文本解密结果,密钥:{key},前100字节:{plain_data[:100]}")
            with open(f"decrypted_text_{key}.txt", "wb") as out_f:
                out_f.write(plain_data)
    except Exception:
        continue

初始疑问解答

  1. 如何找到解密后数据的正确编码?
    只有原文件是纯文本时需要考虑编码,确认解密结果是文本后,可以用chardet这类编码检测库自动识别,不需要无差别遍历所有编码。
  2. 原文件是不可读二进制文件时怎么确认解密成功?
    通过上述的魔数匹配即可判定,匹配到对应魔数的解密结果保存后,直接修改为对应后缀名就能正常打开验证。

内容的提问来源于stack exchange,提问作者Sara Takaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:06:05