使用PyCryptodome解密AES-128 ECB文件无法识别正确密钥如何处理
核心问题排查
首先你现有代码存在3个典型错误,是无有效输出的主要原因:
- 密钥长度不匹配:AES-128要求密钥长度为16字节,你用的32字符密钥如果是十六进制格式,直接用
str.encode()转换会得到32字节(符合AES-256的密钥长度),和题目要求的AES-128不匹配,这是最常见的踩坑点。 - 未处理填充:你自己测试加密时手动加了PKCS7填充,但解密目标文件时没有去掉解密结果末尾的填充字节,就算解密正确,填充字节也会导致文本解码失败、文件格式识别错误。
- 判断逻辑错误:遍历字符编码仅适用于原文件是纯文本的场景,如果原文件是压缩包、图片、办公文档等二进制格式,本身就无法用字符编码解码,自然不会有任何输出。
解决步骤
第一步:修正密钥处理逻辑
如果候选密钥是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
初始疑问解答
- 如何找到解密后数据的正确编码?
只有原文件是纯文本时需要考虑编码,确认解密结果是文本后,可以用chardet这类编码检测库自动识别,不需要无差别遍历所有编码。 - 原文件是不可读二进制文件时怎么确认解密成功?
通过上述的魔数匹配即可判定,匹配到对应魔数的解密结果保存后,直接修改为对应后缀名就能正常打开验证。
内容的提问来源于stack exchange,提问作者Sara Takaya
相关产品推荐
相关产品推荐

