在当今数字世界,数据库存储着大量敏感信息,其中用户密码是最关键的资产之一。数据库密码绝不能以明文(原始文本)形式存储。 明文存储密码无异于将金库钥匙挂在门上——一旦数据库被非法访问(无论是外部黑客攻击还是内部人员滥用权限),所有用户账户将瞬间沦陷,后果不堪设想。
为什么加密还不够?我们需要的是“哈希”
许多人首先想到的是“加密”,加密(Encryption)是一种可逆的过程:使用密钥将原始数据(明文)转换成密文,也能用同一个(对称加密)或配对的另一个密钥(非对称加密)将密文还原成明文,虽然加密比明文存储好,但对于密码存储,加密本身并不是最佳或推荐方案。
原因在于:
- 密钥管理风险: 加密的密码可以被解密,这意味着你必须安全地存储和管理解密密钥,如果攻击者窃取了数据库,同时也窃取了密钥(或者通过其他途径获得密钥),他们就能解密所有密码。
- 目的不匹配: 密码验证通常只需要比较用户输入的密码是否与存储的密码一致,不需要知道密码的原始值,加密保留了原始密码的可恢复性,这超出了验证所需的范围,反而引入了不必要的风险。
行业标准:单向哈希加盐(Hashing with Salt)
数据库密码存储的黄金法则是使用密码学哈希函数(Cryptographic Hash Function),并配合盐(Salt),这是一个单向过程:
-
哈希函数:
- 将任意长度的输入(密码)转换成固定长度、看似随机的字符串(哈希值)。
- 核心特性:
- 确定性: 相同的输入永远产生相同的哈希值。
- 单向性: 从哈希值几乎不可能(在合理时间内)反推出原始输入,这是密码存储安全的基础。
- 雪崩效应: 输入即使发生微小变化(如一个字符),产生的哈希值也会发生巨大、不可预测的变化。
- 抗碰撞性: 极难找到两个不同的输入产生相同的哈希值。
- 重要提示: 不要使用 MD5, SHA-1 等已被证明不安全的快速哈希算法! 它们容易被暴力破解(穷举尝试)或利用预先计算好的彩虹表(Rainbow Table)攻击。
-
盐(Salt):
- 一个随机生成的、足够长(通常16字节或更长)的字符串。
- 核心作用:
- 抵御彩虹表攻击: 彩虹表是预先计算好的常用密码及其哈希值的对照表,加盐意味着即使两个用户使用了相同的密码,由于盐不同,最终存储的哈希值也完全不同,攻击者无法直接使用现成的彩虹表,必须为每个盐单独计算,大大增加攻击成本和难度。
- 确保唯一性: 强制相同密码产生不同哈希。
- 盐的处理:
- 盐必须是每个用户唯一的(每个密码对应一个独立的随机盐)。
- 盐不需要保密,可以与哈希值一起明文存储在数据库中,它的安全性在于其随机性和唯一性,使得攻击无法批量进行。
过程详解:存储与验证
-
用户注册/修改密码时:
- 用户提供密码(
mySecret123
)。 - 系统为该用户生成一个唯一的、强随机盐(
X7!fG2*Kp
)。 - 系统将盐与密码拼接(
X7!fG2*KpmySecret123
)。 - 将拼接后的字符串输入安全的密码哈希函数进行计算,得到哈希值(
a9b8c7d6e5f4g3h2i1j0...
)。 - 将哈希值和盐一起存储到数据库的用户记录中。
- 用户提供密码(
-
用户登录验证时:
- 用户输入用户名和密码(
mySecret123
)。 - 系统根据用户名从数据库取出该用户对应的盐和存储的哈希值。
- 系统将用户输入的密码与取出的盐拼接(
X7!fG2*KpmySecret123
)。 - 将拼接后的字符串输入相同的安全密码哈希函数进行计算,得到一个新的哈希值。
- 系统比较新计算出的哈希值与数据库中存储的哈希值。
- 如果两者完全一致,则密码正确;否则,密码错误。
- 用户输入用户名和密码(
选择安全的密码哈希算法
选择专门为密码存储设计、计算缓慢(故意消耗计算资源)且内存消耗大(抵抗GPU/ASIC硬件加速攻击)的算法至关重要:
- bcrypt: 非常成熟和广泛采用的算法,内置盐,可以调整工作因子(迭代次数)来增加计算成本,对抗硬件性能提升。
- scrypt: 不仅计算成本高,还要求大量内存,使其在抵抗定制硬件攻击方面比 bcrypt 更强。
- Argon2: 这是当前(截至2025年)的推荐首选。 它是 Password Hashing Competition (PHC) 的获胜者,Argon2 提供了高度可配置性(时间成本、内存成本、并行度参数),可以灵活抵御不同类型的攻击(侧重内存或侧重计算),安全性被认为优于 bcrypt 和 scrypt,有 Argon2i, Argon2d, Argon2id 变体,通常推荐 Argon2id。
最佳实践总结
- 绝对禁止明文存储。
- 避免使用普通加密存储密码。
- 强制使用强密码策略(长度、复杂度),提升原始密码强度。
- 使用专门设计的、慢速的密码哈希函数: 优先选择 Argon2 (Argon2id), 其次是 scrypt 或 bcrypt。
- 必须为每个密码使用唯一的、强随机盐。
- 安全地存储盐和哈希值(通常一起存储在用户记录中)。
- 调整工作因子/成本参数: 随着硬件性能提升,定期增加算法的计算成本(迭代次数、内存大小等),使其破解始终困难,目标是验证耗时在几百毫秒级别对用户体验影响不大,但对大规模破解构成巨大障碍。
- 密钥管理(如果涉及加密): 如果系统中其他地方确实需要用到加密(例如加密其他敏感数据),必须使用行业标准的密钥管理解决方案(如硬件安全模块 HSM 或云 KMS)来严格保护密钥,绝不能硬编码在应用代码或配置文件中。
- 定期审查和更新: 安全是持续的过程,关注密码学进展和漏洞披露,评估是否需要迁移到更强大的算法或调整参数。
- 最小权限原则: 确保数据库和应用本身都遵循最小权限原则,限制访问密码存储表的账户权限。
常见错误与警示
- 使用 MD5/SHA-1 哈希: 等同于明文存储,极易破解。
- 不加盐: 对相同密码产生相同哈希,易受彩虹表攻击。
- 盐太短或可预测: 降低了抵御彩虹表攻击的效果。
- 使用自定义加密/哈希方案: 自行设计的方案几乎必然存在未知漏洞,极其危险。
- 硬编码加密密钥: 密钥泄露则所有加密数据暴露。
- 使用过时或快速哈希算法: 如 MD5, SHA-1, SHA-256/SHA-512(如果不加盐且不加慢速处理,对于密码存储也不够安全)。
保护数据库中的用户密码是系统安全的重中之重。采用加盐的慢速密码哈希(如 Argon2, bcrypt, scrypt)是当前行业公认且必须遵循的最佳实践。 这能有效防止密码在数据库泄露后被轻易破解,极大地提升了用户账户的安全性,务必避免使用过时或不安全的方案(如明文、简单加密、MD5/SHA-1哈希),并持续关注密码学发展,及时更新安全措施,保护用户密码不仅是对用户负责,也是维护自身系统信誉和业务安全的关键防线。
引用说明:
- 本文阐述的密码存储最佳实践(加盐慢速哈希)广泛被以下权威机构推荐:
- OWASP (Open Web Application Security Project): OWASP Cheat Sheet Series – Password Storage Cheat Sheet
- NIST (National Institute of Standards and Technology): NIST Special Publication 800-63B – Digital Identity Guidelines – Authentication and Lifecycle Management
- Password Hashing Competition (PHC): https://password-hashing.net/ (Argon2 作为获胜者)
- bcrypt, scrypt, Argon2 等算法的技术细节和安全特性,可参考其官方文档或相关密码学文献。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/35698.html