如何存储密码盐?

12

使用PHP,我正在使用sha256算法的hmac函数对密码进行编码。我不确定的是如何正确地存储盐。

哈希密码的整个目的是为了防止黑客获取数据库访问权。如果我将盐存储在与哈希密码相同的数据库行中,岂不是就像我在将"秘密代码"交给黑客? 这就像我安装了一扇带锁的门,并将钥匙交给入侵者。

请问有人能够解释一下他们是如何存储盐的吗?


你在哪里存储盐字符串? - Janus Troelsen
除非我错了,否则盐是每一行独有的,因此您并没有给他们一个秘密代码,只是配方的一部分。 - David Nguyen
2
盐的作用不在于保密,而是防止攻击者将暴力破解/字典攻击的成本分摊到许多账户或许多服务器上。 - Michael Borgwardt
3个回答

16
将盐放在已经被攻击者窃取的数据库中并不是一个实际问题。将盐与原始密码结合成密码哈希可以防止攻击者使用数百万已知密码哈希的“彩虹表”获得部分被盗用户ID的密码。
将密码和盐混合后进行哈希处理,使得即使针对单个密码破解也变得难度大幅提高,因为盐会使得彩虹表中的已知密码哈希失效。因此,即使攻击者已经知道了每个用户的盐值,在尝试破解任何单个用户时,攻击者必须为该用户计算一个全新的彩虹表,将用户的盐与他们最初的彩虹表中其他密码相结合以破解用户的密码。
加盐并不能使密码变得完全无法破解,但它可以极大地增加破解的难度。例如,攻击者可以拿着哈希和盐值,针对你用户的小部分进行攻击,这也是鼓励用户使用强密码的另一个原因,这样更不可能出现在彩虹表中。

另外需要注意的是,这个好的线程讨论了一些其他的点。http://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough - Ryan Gibbons
3
+1 我只想补充一点,您可以通过添加一个应用程序级别的盐并将其存储在数据库之外的某个地方来进一步阻止攻击者。这样,即使有人获得了数据库,他们仍然会缺少关键信息。 - NullUserException
如果你将盐存储在其他地方,攻击者甚至可能不得不采取最后一个选项——暴力破解,因为他无法计算出彩虹表。 - JanLikar
@JanL 暴力破解将会非常不切实际。如果没有访问所有盐值的权限,哈希值就变得无用了。攻击者只能强制攻击登录页面/脚本本身,而你应该设置速率限制(例如:在5次失败尝试后,阻止账户或要求输入验证码)。 - NullUserException
@NullUserException 这样做的问题在于 IP 欺骗。如果你要求输入验证码,那么就总是要求输入。除非你跟踪某个人尝试登录某个账户的次数,而不是某个 IP 地址尝试登录账户的次数。 - Andrew
1
@Andrew,由于三次TCP握手的存在,伪造IP是不可能的。总是要求填写验证码会给合法用户带来不便。 - NullUserException

3
我建议将盐值与哈希算法的标识符和哈希本身一起存储。
原因如下:
通常,对数据库的访问仅限于localhost或某些预定义的IP地址范围。这意味着,为了获取对您的数据库的访问权限,黑客需要破解您服务器的文件系统(通过直接访问或注入脚本)。或执行SQL注入攻击。
在前一种情况下,这意味着如果有人获得了您在数据库中的盐值,他/她也可以轻松地从您的PHP文件源代码中读取它们。
后一种情况可以通过使用PDOMySQLi的准备语句来简单地防止。您不应再使用旧的mysql_*函数作为API。它们已经不再维护,并且停用过程已经开始
即使有人得到了您的数据库,也不是什么大问题。如果您使用crypt()函数使用良好算法(建议使用CRYPT_BLOWFISH)创建哈希,则破解一个密码甚至可能需要数年时间。在此期间,您可以轻松向用户发送“更改密码”通知,并锁定所有未这样做的用户。
如果您正在使用PHP 5.5+,则应改用新的密码API:http://php.net/password

2

盐被设计为明文并立即可用。密码哈希是完全不可逆的,但可以通过字典攻击破解。因此,需要足够的盐来增加几个数量级,以扰乱字典攻击。公开盐不应降低哈希密码的安全性。


2
“完全不可逆”和“可被字典攻击”不是完全矛盾吗? 完全不可逆意味着您不可能获得原始明文密码,这显然不是事实。” - NullUserException
1
不,你可以通过字典/彩虹表推断出原始密码。但你仍然无法反向哈希。此外,有可能多个输入会产生相同的哈希输出。 - Jé Queue
从刚刚被破解密码的人的角度来看,有什么区别? - NullUserException
1
用户总是会生气的,但是将盐放在哈希旁边或保持分开并不会改变这种责任。 - Jé Queue
不,我的意思是:对于密码被破解的人来说,“reversed”和“inferred”有什么区别? - NullUserException

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接