我应该如何存储密码salt


How should I store a password salt?

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

散列密码的全部目的是为了防止黑客访问数据库。如果我将salt存储在数据库中,与哈希密码位于同一行,难道这不就像我在给黑客"密码"一样吗?我正在装一扇带锁的门,把钥匙递给入侵者。

有人能向我解释一下他们是如何储存盐的吗?

将盐交到窃取数据库的攻击者手中实际上并不是问题。将salt与原始密码组合到密码哈希中,可以防止攻击者使用数百万已知和知名密码哈希的"彩虹表"来获取被盗用户ID的部分的密码。

将密码和salt散列在一起会使破解单个密码的难度增加许多数量级,因为salt会使彩虹表中已知的密码散列失效。因此,即使攻击者知道每个用户的salt,这意味着为了破解任何一个用户,攻击者必须仅为该用户计算一个全新的彩虹表,该表将用户的sal与他们开始使用的彩虹表中已知的其余密码相结合。

Salting密码并不会使不可能破解密码,但要困难得多。例如,攻击者可能会用手中的哈希和salt来攻击一小部分用户,这也是鼓励使用不太可能出现在彩虹表中的强密码的另一个原因。

我会选择将salt与哈希算法的标识符和哈希本身一起存储。

原因如下:

通常,对数据库的访问仅限于localhost或某个预定义的IP地址范围。这意味着,为了让黑客访问您的数据库,他/她需要破坏您的服务器文件系统(通过直接访问或注入脚本)。或者执行SQL注入。

在前一种情况下,这意味着,如果有人在DB中访问了您的盐,他/她可以很容易地从您的PHP文件源中读取它们。

后一种原因可以简单地通过使用PDO或MySQLi准备好的语句来防止。您不应该再使用旧的mysql_*函数作为API。它们不再被维护,贬值的过程已经开始。

即使有人拿到了你的数据库,也没什么问题。如果你使用crypt()函数来创建具有良好算法的哈希(推荐使用CRYPT_BLOWFISH),那么即使破解一个密码也可能非常长(以年为单位)。到那时,您可以轻松地向用户发送"更改密码"通知,并锁定所有尚未更改密码的用户;所以

如果您使用的是PHP 5.5+,则应该使用新密码API:http://php.net/password

salt旨在作为明文并立即可用。密码散列是完全不可逆的,但它是字典可附加的。因此,盐足以增加几个数量级来干扰字典攻击。提供salt不会降低哈希密码的安全性。