【发布时间】:2010-04-06 07:09:42
【问题描述】:
我已经阅读了关于 SO 的许多关于此的问题,但许多答案相互矛盾或我不明白。
您应该始终将密码存储为哈希,而不是纯文本。 但是您是否应该将盐(每个用户唯一的)存储在数据库中的散列密码+盐旁边。这对我来说似乎不是很聪明,因为不能有人访问数据库,查找名为 Admin 的帐户或其他帐户,然后从中计算出密码吗?
【问题讨论】:
我已经阅读了关于 SO 的许多关于此的问题,但许多答案相互矛盾或我不明白。
您应该始终将密码存储为哈希,而不是纯文本。 但是您是否应该将盐(每个用户唯一的)存储在数据库中的散列密码+盐旁边。这对我来说似乎不是很聪明,因为不能有人访问数据库,查找名为 Admin 的帐户或其他帐户,然后从中计算出密码吗?
【问题讨论】:
很多人说“停止彩虹表”,但没有解释彩虹表的作用或为什么会阻止它们。
Rainbow 表是一种巧妙的方法,可以预先计算大量哈希并将它们存储在比天真所需的更少的内存中,您可以使用它们非常快速地反转哈希。 hash = md5(password) 和 hash = sha1(password) 等裸函数的表很常见。
但是,它们可以为任何散列函数生成,可以描述为output = f(input)。如果您对所有用户密码使用站点范围的盐,例如hash = md5(salt+password),您可以构造函数f、f(password) = md5(salt+password)。因此你可以为这个函数生成彩虹表,这需要很长时间,但会让你非常快速地破解数据库中的每一个密码。
如果每个密码的salt不同,你就无法生成一个彩虹表来破解数据库中的所有密码。您可以为每个用户生成一个新用户,但这毫无意义——天真的暴力破解不会更慢。因此,为每个用户设置单独的盐可以阻止彩虹表攻击。
有几种方法可以做到这一点。流行的方式包括:
hash = hashfunction(salt + password)
hash = hashfunction(salt + password + user_id)
hash = hashfunction(global_salt + user_salt + password)
拥有全局盐可能会增加破解密码的一些额外复杂性,因为它可能存储在数据库之外(例如,在代码中),如果发生数据库泄露,攻击者可能无法访问。密码学上我认为它不会增加太多,但实际上它可能会减慢它们的速度。
最后,回答您的实际问题:
将盐与用户数据一起存储不会削弱哈希值。散列函数是单向的:给定密码的散列,即使是未加盐的,也很难找到该密码。加盐背后的动机不是让单个散列更安全,而是让多个散列的集合更安全。一组未加盐的哈希有多种攻击向量:
123、password、god)并查看数据库中是否存在密码,然后入侵这些帐户【讨论】:
Salt 用于增加攻击者查找与存储在数据库中的哈希值匹配的密码所必须花费的时间。通常使用诸如彩虹表(参见http://en.wikipedia.org/wiki/Rainbow_table)之类的查找表来实现此目的。
花费时间的不是查找本身,而是计算彩虹表的时间。添加盐会迫使攻击者重新计算一个新的彩虹表,即使攻击者知道会破坏数据库也是如此
【讨论】:
盐是为了扰乱现有的彩虹表。知道盐没有安全威胁。如果你知道盐,你仍然需要知道密码。
【讨论】:
首先,salt 的主要目的是禁用密码的暴力破解,例如,它可以防止使用彩虹表来快速破解密码。
即使攻击者获得了对数据库的访问权限,从盐中计算出真正的密码也不是那么容易(尤其是如果您没有代码并且不知道密码是如何散列的)。然而,为了增加安全性,我喜欢做的是使用代码中指定的静态哈希对密码进行哈希处理。这样,仅仅破坏数据库是不够的。这种方法的一个例子(在 PHP 中):
$hashed_password = sha1($user_password . $user_salt . $static_salt);
$user_salt 是数据库中每个用户唯一的盐值,$static_salt 是代码设置中某处指定的盐值。
【讨论】:
好吧好吧..这么多讨论......这么多信息。这么多问题......我看到毕竟所有问题都是答案,这里是摘要。
这是我的理解。
好吧..虽然没有完全完成,但我的观点是坏人需要很多时间....但是好人领先一步,以确保他们知道坏人将使用哪些技术来破解。因此,请及时设计出更好的技术。
保重....
【讨论】:
如果你不存储盐,你将如何检查是否提供了正确的密码?
【讨论】: