向pickle字典存储加密信息时遇类型错误,求技术解决方案
问题解决:Pickle存储加密信息时的"参数必须是字符串而非字节"错误
核心错误原因
报错的根本原因是用文本模式打开文件后执行pickle.dump:with open(dictionary, 'a+') as f 里的a+是文本模式,而pickle序列化操作依赖二进制流,因此触发类型不匹配错误。
此外代码还有两个隐性问题:
- 未定义
site变量,函数调用时会直接报错 - 将Fernet加密后的字节转成字符串是多余操作,反而会给后续解密增加额外处理成本(pickle原生支持序列化字节类型)
修复后的代码
import pickle from cryptography.fernet import Fernet # 实际使用中请妥善保存密钥,不要硬编码在代码内 key = Fernet.generate_key() password_dictionary = {} # 初始化空字典,用二进制写入模式 pickle.dump(password_dictionary, open("dictionary.pkl", 'wb')) dictionary = "dictionary.pkl" def encrypt_and_dump(site, username, password): f = Fernet(key) user_pass = f"{username}{password}" b_user_pass = user_pass.encode() encrypted_user_pass = f.encrypt(b_user_pass) # 改用二进制追加+读写模式,同时更新整个字典而非追加单个对象 with open(dictionary, 'ab+') as f_file: # 读取现有字典 f_file.seek(0) try: existing_dict = pickle.load(f_file) except EOFError: existing_dict = {} # 更新字典内容 existing_dict[site] = encrypted_user_pass # 回到文件开头,覆盖写入最新字典 f_file.seek(0) f_file.truncate() pickle.dump(existing_dict, f_file) # 调用示例 encrypt_and_dump("example.com", "user123", "pass456")
读取解密示例代码
def load_and_decrypt(site): f = Fernet(key) with open(dictionary, 'rb') as f_file: password_dict = pickle.load(f_file) encrypted_data = password_dict.get(site) if encrypted_data: decrypted_data = f.decrypt(encrypted_data).decode() # 注意:如果是拼接用户名和密码加密,需按规则拆分,建议改为加密元组(username,password) username = decrypted_data[:8] # 示例按固定长度拆分,实际按需调整 password = decrypted_data[8:] return username, password return None, None # 调用示例 user, pwd = load_and_decrypt("example.com") print(user, pwd)
额外建议
- 密钥不要硬编码,建议存储在环境变量或加密的配置文件中
- 避免将用户名和密码拼接后加密,直接加密
(username, password)元组更安全,也省去拆分步骤
内容的提问来源于stack exchange,提问作者Makayla Galbraith
相关产品推荐
相关产品推荐

