网站安全防护
用户密码哈希算法选择与安全实践

密码存储是网站安全体系中最基础也最关键的环节之一。历史上多次大规模数据泄露事件表明,一旦密码以明文或弱哈希方式存储,攻击者可以在极短时间内还原出大量用户密码。选择合适的哈希算法并正确实施,是保障用户账户安全的第一道防线。

为什么不能使用MD5和SHA系列

MD5和SHA-1、SHA-256等通用哈希算法在设计之初就不是为了密码存储而服务的。它们的核心目标是计算速度,这意味着同样的硬件条件下,攻击者每秒可以尝试数以亿计的密码组合。现代GPU和专用硬件的出现,进一步加剧了这一问题,使得基于字典和彩虹表的攻击变得非常高效。

此外,MD5和SHA-1已被证明存在碰撞漏洞,虽然碰撞攻击不等于密码破解,但足以说明这些算法不再适合作为安全敏感场景的首选。对于新项目,应当坚决避免使用这些算法存储密码。

专用密码哈希算法对比

bcrypt是当前使用最广泛的密码哈希算法之一。它内置了盐值生成机制,并支持通过cost参数调节计算开销。每次调用bcrypt都会产生不同的哈希结果,有效防止了彩虹表攻击。cost参数每增加一,计算时间翻倍,开发者可以根据硬件性能选择合适的平衡点。

Argon2是2015年密码哈希竞赛的获胜者,相比bcrypt它在抵抗GPU和ASIC攻击方面有更好的表现。Argon2id混合了抗侧信道攻击和抗GPU攻击的特性,是目前推荐的默认选择。它支持调节内存使用量、迭代次数和并行度三个参数,为不同场景提供了灵活的调优空间。

scrypt是另一个可选方案,它通过要求大量内存来提高攻击成本,在抵抗硬件加速攻击方面也有不错的表现。不过其参数调优相对复杂,社区生态不如前两者丰富。

盐值的作用与注意事项

盐值的核心作用是让相同密码产生不同的哈希结果,从而使预计算攻击失效。bcrypt和Argon2都内置了盐值处理,开发者无需手动管理。但如果使用旧式哈希方案,盐值必须使用密码学安全的随机数生成器产生,长度不少于十六字节,且每个用户使用独立的盐值。

一个常见的错误是将盐值硬编码为固定字符串。这种做法虽然比无盐好,但一旦盐值泄露,攻击者就可以针对所有用户构建彩虹表。正确的做法是让每个用户拥有独立的随机盐值,并将盐值与哈希结果一同存储。

密码迁移与升级策略

当系统需要从旧算法迁移到新算法时,不必要求所有用户立即重设密码。可以在用户下次登录时验证旧哈希,验证通过后用新算法重新哈希并替换存储。对于长期未登录的账户,可以设置一个过渡期限,超期后强制要求重置密码。这种平滑迁移策略既提升了安全性,又不会对用户体验造成太大影响。