
本文详解 cryptography.fernet.Fernet 解密失败的核心原因——传入 decrypt() 的参数类型错误,并提供完整、健壮的解密流程,涵盖密钥加载、文件读取、异常处理及安全注意事项。
本文详解 `cryptography.fernet.fernet` 解密失败的核心原因——传入 `decrypt()` 的参数类型错误,并提供完整、健壮的解密流程,涵盖密钥加载、文件读取、异常处理及安全注意事项。
在使用 cryptography 库的 Fernet 进行对称加密/解密时,一个高频错误是向 key.decrypt() 方法传入了文件对象(io.BufferedReader)而非字节数据。正如报错信息所示:
TypeError: token must be bytes or str
该错误明确指出:decrypt() 仅接受 bytes 或 str 类型的加密令牌(即密文),而你的代码中直接传入了 f(一个打开的文件对象):
decryption = key.decrypt(f) # ❌ 错误:f 是文件对象,不是密文内容
正确的做法是:先读取文件全部内容为 bytes,再将其传给 decrypt()。同时需注意密钥本身的加载方式——Fernet 构造器严格要求密钥为 bytes,且必须是原始的 32 字节 URL 安全 Base64 编码字符串(由 Fernet.generate_key() 生成)。
以下是修复后的完整、生产就绪的解密脚本:
立即学习“Python免费学习笔记(深入)”;
from cryptography.fernet import Fernet import os # ✅ 正确加载密钥:必须以二进制模式读取,并保持 bytes 类型 with open("mykey.key", "rb") as key_file: key_bytes = key_file.read().strip() # 去除可能的换行或空格 # 验证密钥格式(可选但推荐) if len(key_bytes) != 44 or b'=' not in key_bytes[-2:]: raise ValueError("Invalid Fernet key: must be 32-byte URL-safe base64-encoded string") fernet = Fernet(key_bytes) # 指定目标目录(注意:路径需为绝对路径或确保工作目录正确) target_dir = r"C:UsersbottaDesktopHarmless Folder" # 遍历目录下所有文件(建议排除非加密文件,如 .key 文件本身) for filename in os.listdir(target_dir): filepath = os.path.join(target_dir, filename) # 跳过目录和密钥文件,避免误操作 if os.path.isdir(filepath) or filename == "mykey.key": continue try: with open(filepath, "rb") as f: encrypted_data = f.read() # ✅ 正确:读取为 bytes # ✅ 解密:传入 bytes 类型的密文 decrypted_data = fernet.decrypt(encrypted_data) # 输出解密后的内容(假设为 UTF-8 文本) print(f"✅ 解密成功 [{filename}]:") print(decrypted_data.decode('utf-8', errors='replace')) print("-" * 50) except Exception as e: print(f"❌ 解密失败 [{filename}]: {type(e).__name__}: {e}")
关键要点与注意事项:
- 密钥必须为 bytes:Fernet 不接受字符串形式的密钥,即使内容相同。务必用 “rb” 模式读取 .key 文件。
- 密文必须为 bytes:decrypt() 的输入是原始加密后的字节流,不是文件句柄。
- 不要重复调用 .read():原代码中 f.read().encode(…) 是错误的——文件已以 “rb” 打开,f.read() 返回的就是 bytes,无需再 encode();后续 f.read() 将返回空字节(因文件指针已在末尾)。
- 添加异常处理:加密文件可能损坏、被篡改或使用不同密钥加密,decrypt() 会抛出 InvalidToken 等异常,应捕获并提示。
- 路径安全:使用 os.path.join() 构建路径,避免硬编码反斜杠导致跨平台问题;考虑使用 pathlib.Path 提升可读性。
- 安全提醒:Fernet 保证加密数据的机密性与完整性,但不提供密钥管理功能。切勿将密钥与加密文件共存于同一目录且无访问控制。
遵循以上规范,即可稳定、安全地批量解密 Fernet 加密的文件。