bcrypt更适合存密码,因其专为密码哈希设计,内置加盐与可调慢速机制;而hashlib.sha256是通用哈希函数,无加盐和延时能力,直接使用存在安全风险。

bcrypt比hashlib.sha256更适合存密码,不是因为它“更强”,而是设计目标不同
bcrypt是专为密码哈希设计的算法,内置加盐、可调慢速(work factor),能有效抵抗暴力和彩虹表攻击;hashlib.sha256只是通用哈希函数,没加盐逻辑,也没计算延时,直接用它存密码等于裸奔。
- 用
hashlib.sha256手动拼接盐值(比如sha256(salt + password))容易漏掉盐的存储/验证一致性,且无法控制计算耗时 - bcrypt生成的哈希字符串自带盐和轮数(如
$2b$12$...),验证时bcrpyt.checkpw()自动提取并复用,不需你操心盐怎么存 - Python标准库没原生bcrypt,得装
bcrypt包:pip install bcrypt(注意:Windows用户可能需要先装Visual Studio Build Tools或用pybcrypt替代)
用bcrypt.hashpw()生成密码哈希时,password必须是bytes,不是str
这是最常卡住新手的地方——传入"mypassword"会报TypeError: Unicode-objects must be encoded before hashing,因为bcrypt底层只认bytes。
- 正确做法:用
.encode("utf-8")显式转码,例如bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()) -
bcrypt.gensalt()默认使用2b版本和轮数12,够用;想调慢点可传rounds=14,但别盲目拉高,影响登录响应 - 生成结果是
bytes类型,存数据库前通常转成str(用.decode("utf-8")),否则ORM可能报错
验证密码用bcrypt.checkpw(),别自己拿hashlib比对
有人把bcrypt哈希存进数据库后,取出再用hashlib.sha256重算一遍去比对——这完全失效,因为bcrypt哈希里混着动态盐和迭代过程,没法用别的算法复现。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 必须用
bcrypt.checkpw(password.encode("utf-8"), hashed_password_from_db.encode("utf-8")) - 第二个参数如果是从DB读出的
str,记得.encode("utf-8");如果DB字段是bytes类型(如PostgreSQL的bytea),就不用再编码 - 即使密码错,
checkpw()也保持恒定耗时(内部做了防时序攻击的填充),这点比手写比较安全得多
别在Django/Flask里重复造轮子:框架已封装好bcrypt流程
如果你用Django,User.set_password()默认就走bcrypt(只要PASSWORD_HASHERS配置没动);Flask-SQLAlchemy项目配了Flask-Bcrypt后,bcrypt.generate_password_hash()和bcrypt.check_password_hash()也是一样逻辑。
- 自己手动调用
bcrypt库没问题,但别为了“看起来更底层”绕过框架封装——比如Django里还自己写hashpw,反而容易漏掉is_password_usable()这类校验 - 检查
settings.py里的PASSWORD_HASHERS,确保'django.contrib.auth.hashers.BCryptPasswordHasher'在列表靠前位置,否则新密码可能被存成pbkdf2_sha256 - 迁移旧密码?Django支持多哈希器共存,老密码仍能验证,新设密码自动升级为bcrypt
真正难的不是选哪个函数,而是盐要不要自己管、哈希要不要存进字段、错误提示会不会暴露用户存在——这些细节藏在业务逻辑里,不在hashpw那一行代码上。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










