【问题标题】:Salt, passwords and security盐、密码和安全性
【发布时间】:2010-04-06 07:09:42
【问题描述】:

我已经阅读了关于 SO 的许多关于此的问题,但许多答案相互矛盾或我不明白。

您应该始终将密码存储为哈希,而不是纯文本。 但是您是否应该将盐(每个用户唯一的)存储在数据库中的散列密码+盐旁边。这对我来说似乎不是很聪明,因为不能有人访问数据库,查找名为 Admin 的帐户或其他帐户,然后从中计算出密码吗?

【问题讨论】:

标签: security passwords salt


【解决方案1】:

很多人说“停止彩虹表”,但没有解释彩虹表的作用或为什么会阻止它们。

Rainbow 表是一种巧妙的方法,可以预先计算大量哈希并将它们存储在比天真所需的更少的内存中,您可以使用它们非常快速地反转哈希。 hash = md5(password)hash = sha1(password) 等裸函数的表很常见。

但是,它们可以为任何散列函数生成,可以描述为output = f(input)。如果您对所有用户密码使用站点范围的盐,例如hash = md5(salt+password),您可以构造函数ff(password) = md5(salt+password)。因此你可以为这个函数生成彩虹表,这需要很长时间,但会让你非常快速地破解数据库中的每一个密码。

如果每个密码的salt不同,你就无法生成一个彩虹表来破解数据库中的所有密码。您可以为每个用户生成一个新用户,但这毫无意义——天真的暴力破解不会更慢。因此,为每个用户设置单独的盐可以阻止彩虹表攻击。

有几种方法可以做到这一点。流行的方式包括:

  • 每个用户的单独盐,与他们的其他详细信息一起存储在数据库中:hash = hashfunction(salt + password)
  • 全局盐和每个用户的一些唯一值:例如hash = hashfunction(salt + password + user_id)
  • 全局盐和每个用户盐:hash = hashfunction(global_salt + user_salt + password)

拥有全局盐可能会增加破解密码的一些额外复杂性,因为它可能存储在数据库之外(例如,在代码中),如果发生数据库泄露,攻击者可能无法访问。密码学上我认为它不会增加太多,但实际上它可能会减慢它们的速度。

最后,回答您的实际问题:

将盐与用户数据一起存储不会削弱哈希值。散列函数是单向的:给定密码的散列,即使是未加盐的,也很难找到该密码。加盐背后的动机不是让单个散列更安全,而是让多个散列的集合更安全。一组未加盐的哈希有多种攻击向量:

  • 彩虹桌
  • 散列常用密码(123passwordgod)并查看数据库中是否存在密码,然后入侵这些帐户
  • 在数据库中寻找相同的哈希值,这意味着相同的密码(可能)

【讨论】:

  • “一个全局哈希和一个每个用户的哈希”是指“一个全局 salt 和一个每个用户 salt”,对吗?其他句子类似...
  • “salt + password”中的“+”是字面加法的意思吗?
  • + 用于表示组合,在实践中通常是串联。但是我不想说“这是正确的做法”,因为老实说,我不知道在这个构造中是否有任何微妙的错误需要避免。正确的答案是你应该使用一个现代的密码哈希库来为你处理这个问题——这些细节不应该在你的控制之下。
【解决方案2】:

Salt 用于增加攻击者查找与存储在数据库中的哈希值匹配的密码所必须花费的时间。通常使用诸如彩虹表(参见http://en.wikipedia.org/wiki/Rainbow_table)之类的查找表来实现此目的。

花费时间的不是查找​​本身,而是计算彩虹表的时间。添加盐会迫使攻击者重新计算一个新的彩虹表,即使攻击者知道会破坏数据库也是如此

【讨论】:

  • 盐也使存储的哈希值唯一,即使两个用户具有相同的密码。
  • @Anders Abel - 仅统计数据。当然,这确实取决于盐的大小和用户群,但是对于旧的基于 UNIX DES 的密码散列,盐只有 12 位,所以如果我们有 4097 个使用相同密码的用户,至少有两个将具有相同的密码哈希。
  • 计算一个彩虹表对于 100,000 个用户来说是完全值得的。关键是,如果每个用户的盐不同,你就无法做到这一点——计算 100,000 个彩虹表将毫无意义。
【解决方案3】:

盐是为了扰乱现有的彩虹表。知道盐没有安全威胁。如果你知道盐,你仍然需要知道密码。

【讨论】:

  • 但是如果 salt + password = hash 那么 hash - salt = password?
  • 松散地说,但请记住哈希是一种单向算法。 [ do_hash(盐+密码)= hashed_pa​​ssword。 ] 如果知道 salt,攻击者必须为每次密码尝试执行 do_hash(salt + password_guess),以便构建彩虹表或暴力/字典攻击每个密码。更改每个用户的盐,这会留下一个非常大的搜索空间。
  • 但是为什么攻击者想要所有用户的密码肯定他只会寻找管理员等。
  • @Jonathan 这不仅仅是管理员的密码。许多人在不同的网站上使用相同的密码。这样,您可以更安全地保护他们的密码,这样攻击者就无法从您的数据库中获取他们的密码。
【解决方案4】:

首先,salt 的主要目的是禁用密码的暴力破解,例如,它可以防止使用彩虹表来快速破解密码。

即使攻击者获得了对数据库的访问权限,从盐中计算出真正的密码也不是那么容易(尤其是如果您没有代码并且不知道密码是如何散列的)。然而,为了增加安全性,我喜欢做的是使用代码中指定的静态哈希对密码进行哈希处理。这样,仅仅破坏数据库是不够的。这种方法的一个例子(在 PHP 中):

$hashed_password = sha1($user_password . $user_salt . $static_salt);

$user_salt 是数据库中每个用户唯一的盐值,$static_salt 是代码设置中某处指定的盐值。

【讨论】:

  • 我不相信这只会给人一种虚假的安全感。
  • 就像 Grimmy 所说,如果有人破坏了数据库并获取了用户的哈希密码和盐,他们可以使用这些来生成新的彩虹表(假设他们知道所使用的哈希方法,您可以在开源软件的案例)。如果您还在散列密码中包含未存储在数据库中的盐,则攻击者无法仅通过破坏数据库来生成新的彩虹表。这不仅仅是虚假的安全感。
  • 如果每个用户有不同的盐,你就不能生成彩虹表。我看到 reko_t 建议使用了很多,我也不确定它是否真的增加了安全性。我对一种情况有一个想法:如果您有一个非常大的数据库,并且每个密码哈希都像他所说的那样,但没有静态盐:您可以为每个用户运行一些查询,例如 hash "1234" + user_salt 和存储匹配。你肯定会泄露一些帐户。如果存在未知的全站哈希,则无法使用此向量,并且很难找到哈希。
【解决方案5】:

好吧好吧..这么多讨论......这么多信息。这么多问题......我看到毕竟所有问题都是答案,这里是摘要。

  1. 为什么是盐?
  2. 为什么 Salt 与(密码 + salt)的哈希一起存储。

这是我的理解。

  1. 黑客为他辛辛苦苦制作的所有字典单词都有彩虹表。每一个彩虹表的制作都会让黑客见鬼去吧。简而言之,它非常艰难。
  2. 至于第 1 点,如果我们让黑客为每个用户计算彩虹表,那么当他知道密码时,他就会变老。而如果用户经常更改密码,那么即使是黑客的孙子,在他们知道密码时也会变老。
  3. 好的。因此,为每个用户使用不同的盐。这使得黑客可以使用单独的攻击来知道每个用户的密码。
  4. 我看到许多读者指出,一个伟大的黑客不会对每个用户进行攻击,而是将他所有的精力放在管理员帐户上,然后他就完成了 :)。所以在这种情况下,我们会先一步,然后使用一些不同的方法来计算哈希。可以说盐不完全是存储的。它可能是实际哈希的一半。另一半以其他方式存储在其他地方(以其他方式计算)。这只是一个额外的安全措施。而且我们知道,在当今时代,计算机的计算能力正在增加。所以有道德的人知道,世界上最快的超级计算机将需要 1 年时间来破解管理员密码(只是一个例子)。因此,他们强制执行一项政策,即每 3 个月更改一次管理员密码。当黑客知道旧密码时,新密码已经生效。或者说数据库被入侵了,那么当黑客破解密码时,好人就会知道它。到那时,好人会改变事情(记得升级算法..sha1 sha2 和现在的sha3).....

好吧..虽然没有完全完成,但我的观点是坏人需要很多时间....但是好人领先一步,以确保他们知道坏人将使用哪些技术来破解。因此,请及时设计出更好的技术。

保重....

【讨论】:

    【解决方案6】:

    如果你不存储盐,你将如何检查是否提供了正确的密码?

    【讨论】:

    • 我的意思是你应该将它存储在主数据库中而不是其他地方
    • @Jonathan - 除了登录名和密码列之外,将其存储在同一个数据库表中。盐是否受损并不重要。
    猜你喜欢
    • 2012-07-05
    • 2016-07-28
    • 2016-04-06
    • 2013-08-23
    • 2010-09-28
    相关资源
    最近更新 更多