加密用于可逆保护数据机密性,如Fernet存储API密钥;哈希用于不可逆验证完整性,如bcrypt存密码;二者不可互换,错误使用会导致安全漏洞或功能失效。

加密和哈希在 Python 中常被混用,但它们解决的问题完全不同:加密是可逆的,用于保护数据机密性;哈希是不可逆的,用于验证数据完整性或身份。选错方法可能导致安全漏洞或功能失效。
什么时候该用加密(如 Fernet、AES)
当你需要之后还原原始数据时,必须使用加密。典型场景包括:存储用户敏感信息(如 API 密钥、支付令牌)、传输前保护配置项、实现端到端消息保密。
- Python 标准库 cryptography 提供 Fernet(对称加密,简单易用),适合单密钥场景
- 避免自己实现 AES 模式(如 CBC、GCM),优先用 Fernet 封装,它自动处理 IV、填充和认证
- 密钥必须安全保管——不能硬编码,建议用环境变量 + 密钥管理服务(如 HashiCorp Vault)
什么时候该用哈希(如 hashlib、bcrypt)
当你只需要确认“数据没被篡改”或“密码是否正确”,且不需要还原原文时,必须用哈希。典型场景包括:密码存储、文件校验、API 签名比对。
- 存密码绝不用 hashlib.sha256(password.encode()) —— 它太快、无盐、易被彩虹表攻击
- 用 bcrypt 或 passlib,它们内置加盐与自适应迭代,能抵御暴力破解
- 校验文件或接口签名可用 hashlib.sha256(),但需注意:相同输入永远得相同输出,不涉及密钥
别把哈希当加密来“解密”
有人尝试用字典攻击或查表“反解” SHA256,这是误解哈希本质。SHA256 不是加密算法,没有密钥,也没有解密过程。它的设计目标就是单向性。
立即学习“Python免费学习笔记(深入)”;
- 若业务逻辑要求“找回密码”,说明需求本身错误——应提供重置流程,而非解密
- 用哈希做“token 验证”时,如果还希望携带有效期或用户 ID,应改用 JWT(含签名+载荷)或加密 token
- 哈希值比较务必用 hmac.compare_digest(),防止时序攻击
加密与哈希混合使用的合理场景
真实系统中二者常配合:例如登录流程中,密码用 bcrypt 哈希存储;登录成功后生成的 session token 用 Fernet 加密,防止客户端篡改。
- 上传文件时,先计算 sha256(file) 存入数据库,下载时再校验——这是哈希
- 同一文件内容若需加密传输,则用 AES 加密后发送,并附上加密前的哈希值供接收方校验完整性——这是组合
- 不要对哈希值再加密(如 encrypt(sha256(pwd)))——既不增加安全性,又引入冗余复杂度










