密码哈希
我们都知道,在 21 世纪,密码永远不应该以明文形式保存。
-
但是,这并不能减少在某些 API 调用期间以明文形式发送密码值的机会。
-
主要担心的是数据库落入坏人之手,使得恢复原始文本变得不可能。
-
接下来会发生的是数据库将是“凭证填充”。相同的凭据将在具有相同用户名的不同帐户上一次又一次地尝试:电子邮件、银行卡、社交媒体、学校,甚至政府帐户。
为什么不使用加密而是使用散列?
-
关键区别在于可逆性。加密是一个可逆过程,这意味着使用正确的密钥可以恢复原始明文密码。即使加密密钥得到安全管理,这也会带来安全风险。
-
此外,管理加密密钥(例如构建密钥链)可能会产生巨大的成本和复杂性。
为什么需要盐
-
Salt 为每个散列密码添加随机性,使得攻击者使用彩虹表等预先计算的表破解密码的计算成本很高(将在下面解释)。
-
如果没有盐,攻击者可以通过将哈希值与预先计算的哈希值的大型数据库进行比较来有效地猜测密码。
-
此外,盐对于每个密码必须是唯一的,而不仅仅是每个用户。这确保了即使两个用户具有相同的密码,由于盐的独特性,它们的哈希值也会不同,从而防止攻击者轻松识别重复的密码。
使用哈希的不同目的
Sha3 比 md5 更安全,为什么不使用 sha3?哈希不仅仅用于密码值,还有不同的用例:
-
数据完整性(例如 SHA3):SHA3 等哈希算法通常用于对文件进行指纹识别,以确保其完整性保持不变。这些算法需要在速度和哈希抗碰撞性之间取得平衡。虽然 SHA3 提供了良好的抗碰撞性,但它也为文件指纹识别任务保持了合理的性能。
-
校验和(例如 CRC32):当速度至关重要时,例如在网络传输期间验证数据完整性时,CRC32 等算法表现出色。CRC32 通常用于快速识别文件在传输过程中是否被修改,优先考虑效率而不是抗碰撞性。
-
密钥生成(例如 Argon2、bcrypt、PBKDF2):为了安全地存储密码或生成加密密钥,首选 Argon2、bcrypt 或 PBKDF2 等专用密钥派生函数 (KDF)。这些算法有意引入“缓慢”的哈希过程,增加计算复杂性层以对抗哈希碰撞暴力攻击。
虽然 SHA3 适用于HTTPS 连接或JWT 令牌签名生成等任务,但它缺乏提供密码哈希所需的高度安全性所需的速度。
为什么 KDF 在散列密码中很重要
KDF 通过故意减慢哈希过程,在密码哈希中发挥着至关重要的作用。这种故意的减慢是通过哈希值计算的多次迭代来实现的。虽然这些迭代的技术细节可能很复杂,但它们本质上涉及重复操作,例如对哈希值进行移位、反转和异或运算,并执行数千轮。
在密码中使用 KDF 的主要目的是:
-
减慢进程:通过引入计算开销,KDF 大大增加了攻击者暴力破解密码的难度。计算哈希值所需的时间和计算资源增加,可有效阻止快速字典或彩虹表攻击。
-
资源消耗:KDF 在哈希过程中也会消耗大量的 CPU 和内存资源。这种资源密集型性质进一步阻碍了攻击者,因为他们必须投入大量的计算能力和时间来破解散列密码。
什么是彩虹表攻击?
简短解释一下。
-
词典表。在彩虹表之前,攻击者预先计算所有哈希值,并枚举一个名为“字典表”的表中的所有哈希值,然后在获取目标数据库表后,进行哈希碰撞并获取链接的原始密码值(这也是为什么盐是如此重要)
-
然而,字典表可能会增长得非常快,最终会因行数过多而变得无法使用。
-
彩虹表可以被认为是“字典表的高效版本”
-
在彩虹表中,有 2 个函数。H:从明文得到哈希值,R:从哈希值得到明文
-
存储多行。每一行都是一个“哈希链”,每一行都以纯文本开始,然后多次执行 H 和 R。
-
与目标数据库表进行哈希碰撞,一旦哈希值匹配,就进行R以获取明文。
最后的
为什么 md5 (或 sha1) 不能用于密码值哈希?如果是,md5 还有其他用例吗?
原文始发于微信公众号(KK安全说):密码应该如何存储?
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论