
本文详解 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:\Users\botta\Desktop\Harmless 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 加密的文件。










