Python中如何使用加盐哈希算法处理pickle格式字典文件
操作方案
首先先修复你现有代码的笔误:check_password函数的形参误写为sored_password,运行会触发变量未定义错误,修正后和pickle处理逻辑整合即可使用。
处理pickle存储的密码字典的完整流程如下:
- 加载pickle文件反序列化为Python字典对象,操作前务必备份原文件,避免数据损坏
- 遍历字典中存储明文密码的字段,调用
hash_password生成带随机盐的哈希值,替换原有明文 - 将处理完成的字典重新序列化写回pickle文件
- 后续密码校验时,从pickle中读取预存的哈希值,调用
check_password和用户输入的明文比对即可
注意事项
- 每次调用
hash_password都会生成全新的随机盐,同一明文每次生成的哈希值不同,这是正常的安全设计,不影响校验逻辑 - 本方案生成的哈希值固定为192位长度(64位盐+128位PBKDF2哈希结果),可以通过长度判断字段是否已经完成哈希,避免重复处理
- pickle反序列化存在任意代码执行风险,绝对不要加载来源不可信的pickle文件
完整可运行代码
import hashlib import binascii import os import pickle # 修正后的加盐哈希工具函数 def hash_password(password): salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii') password_hash = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), salt, 100000) password_hash = binascii.hexlify(password_hash) return (salt + password_hash).decode('ascii') def check_password(stored_password, user_password): salt = stored_password[:64] stored_password = stored_password[64:] password_hash = hashlib.pbkdf2_hmac('sha512', user_password.encode('utf-8'), salt.encode('ascii'), 100000) password_hash = binascii.hexlify(password_hash).decode('ascii') return password_hash == stored_password def process_pickle_passwords(pickle_path, password_field=None): # 读取原pickle文件 with open(pickle_path, 'rb') as f: data = pickle.load(f) if not isinstance(data, dict): raise ValueError("目标pickle文件反序列化结果不是字典类型,请检查文件") # 适配两种常见字典结构 if password_field is None: # 结构为 {用户标识: 明文密码} for key in data: if isinstance(data[key], str) and len(data[key]) != 192: data[key] = hash_password(data[key]) else: # 结构为 {用户标识: {..., "密码字段名": 明文密码, ...}} for key in data: if isinstance(data[key], dict) and password_field in data[key]: pwd_val = data[key][password_field] if isinstance(pwd_val, str) and len(pwd_val) != 192: data[key][password_field] = hash_password(pwd_val) # 写回处理后的数据 with open(pickle_path, 'wb') as f: pickle.dump(data, f) # 调用示例 if __name__ == "__main__": # 替换为你的pickle文件路径,嵌套结构传入password_field参数指定密码键名 process_pickle_passwords("user_passwords.pkl", password_field="password") # 功能测试 with open("user_passwords.pkl", "rb") as f: pwd_db = pickle.load(f) # 替换为实际存在的用户和对应原密码 print(check_password(pwd_db["demo_user"]["password"], "original_plain_pwd")) print(check_password(pwd_db["demo_user"]["password"], "wrong_pwd"))
内容的提问来源于stack exchange,提问作者soft
相关产品推荐
相关产品推荐

