题目
设计安全的用户密码存储方案
信息
- 类型:问答
- 难度:⭐⭐
考点
密码哈希算法,盐值应用,防彩虹表攻击,工作因子调整
快速回答
安全密码存储的核心要点:
- 使用抗碰撞的哈希算法(如bcrypt/scrypt/Argon2)
- 为每个密码生成唯一随机盐值(16字节以上)
- 设置动态工作因子(如bcrypt的cost值≥12)
- 存储格式包含算法标识+盐值+哈希结果
- 绝对禁止明文存储或使用弱哈希(MD5/SHA1)
原理说明
密码存储的核心原则是不可逆性和抗暴力破解:
- 哈希算法:将密码转化为固定长度的字符串,理想算法需抵抗碰撞攻击和预映射攻击
- 盐值(Salt):随机字符串,使相同密码产生不同哈希值,防止彩虹表攻击
- 工作因子(Work Factor):增加计算成本,使暴力破解效率大幅降低
代码示例(Python bcrypt实现)
import bcrypt
# 密码存储流程
password = b"user_password_123"
salt = bcrypt.gensalt(rounds=12) # 工作因子=12
hashed = bcrypt.hashpw(password, salt)
# 存储格式示例:$2b$12$3euPcmQf1KaWfU83Z5wjf.3oB7F3YbJj4G6dKtVnMsL9JkXrV8D/S
# 密码验证流程
input_password = b"user_input_password"
if bcrypt.checkpw(input_password, hashed):
print("Password correct")
else:
print("Invalid password")最佳实践
- 算法选择优先级:Argon2 > scrypt > bcrypt > PBKDF2(避免SHA/MD5系列)
- 盐值规范:使用CSPRNG生成,长度≥16字节,与哈希结果分开存储
- 工作因子调整:bcrypt的cost值应≥12(每增1耗时翻倍),定期评估硬件升级影响
- 存储格式:采用标准化格式如
$algorithm$work_factor$salt$hash
常见错误
- 固定盐值:使攻击者能构建针对性彩虹表
- 迭代次数不足:如bcrypt cost<10时可在毫秒级完成计算
- 短盐值:盐值<8字节大幅降低熵值
- 自定义哈希:如
sha256(salt + password)易受长度扩展攻击 - 错误比较方式:未使用恒定时间比较函数可能引入时序攻击漏洞
扩展知识
- 彩虹表原理:预计算的哈希-明文对照表,盐值可有效防御
- 密钥派生函数(KDF):bcrypt等本质是设计为慢速的KDF
- GPU/ASIC抵抗:Argon2和scrypt需大量内存,限制硬件并行加速
- 密码策略联动:存储方案需配合密码强度策略(长度/复杂度)
- OWASP推荐:2023年建议工作因子使单次哈希耗时0.5-1秒