解密cryptography库Fernet编码PIN校验输入及TypeError报错处理
问题原因分析
报错与逻辑异常由以下错误导致:
- 触发
TypeError: token must be bytes的直接原因:使用文本模式'r'读取.key文件,获取的内容为字符串类型,但Fernet的decrypt方法要求传入的加密token必须是bytes类型。 - 逻辑错位:已通过
readlines()遍历文件内容后,文件指针已移动到末尾,后续pid_file.read()无法读取到有效内容;同时错误将fer.decrypt()的返回值作为read()的长度参数,decrypt会直接返回解密后的明文bytes,无需再调用文件读取方法。 - 类型与逻辑错误:
data.split()返回值为列表,无法直接传入decrypt方法;解密后得到的是bytes类型,调用encode()属于错误类型转换,正确操作为将bytes转为字符串后与用户输入比对。
修正后代码示例
需要使用加密PIN时相同的Fernet密钥初始化实例,不能使用新生成的密钥,示例如下:
from cryptography.fernet import Fernet # 读取你加密时使用的Fernet密钥,替换为你实际的密钥存储路径 with open("fernet_secret.key", 'rb') as f: fernet_key = f.read() fer = Fernet(fernet_key) def get_pin(): pid_input = input("Enter your pin : ") # 用二进制模式读取加密后的PIN文件 with open("PID.key", 'rb') as pid_file: encrypted_pid = pid_file.read().strip() try: # 解密后转成utf-8字符串 decrypted_pid = fer.decrypt(encrypted_pid).decode("utf-8") except Exception: # 解密失败(密钥错误、文件被篡改等)直接退出 exit() if pid_input != decrypted_pid: exit()
存储方案说明
- 使用.key扩展名存储加密后的PIN本身不存在不合理问题,扩展名仅为文件标识,不影响功能实现,只要做好文件权限管控即可。
- 注意加密用的Fernet密钥不能和加密后的PIN存储在同一位置,否则攻击者同时拿到两个文件即可直接解密获取明文PIN,失去加密意义。
- 若PIN为短位数纯数字密码,即使加密存储也存在暴力破解风险,建议适当提升PIN复杂度。
内容的提问来源于stack exchange,提问作者MundaneHassan
相关产品推荐
相关产品推荐

