【问题标题】:Reason for salting a password for webservice为 web 服务加盐密码的原因
【发布时间】:2018-06-14 05:08:47
【问题描述】:

我有一个与用户管理相关的非常基本的问题,尤其是存储散列密码。 我读了几页(比如https://wiki.python.org/moin/Md5Passwords)。 我理解散列的方式是这样的:

  • 用户提供的密码以一种方式散列(使用任何函数)。
  • 没有人(包括用户/管理员)可以看到密码。
  • 当用户登录时 - 对他提供的字符串进行哈希处理,以查看它是否与存储的哈希密码匹配。

这一切都很清楚,但是我不确定散列中的“盐”是什么。 我读过 os.urandom (Python) 可以很好地创建好盐: https://crackstation.net/hashing-security.htm

我不确定如何使用这种添加的“盐” 如果我用盐和它的一种方式散列用户密码。下次用户登录时,他只知道密码而不知道盐。据此,我假设为该用户生成的“盐”需要存储在某个地方。否则就没有意义了。但另一方面,如果有人可以访问数据库,那么将看到“salt”和散列密码。在这种情况下,“盐”不会增加太多价值(它与散列纯密码几乎相同)。所以也许“盐”只是为了防止前端保护(反对蛮力)。

有人可以告诉我如何使用盐吗?我的理解是否正确。我需要在某处储存“盐”吗?

在我发布这个问题之前,我发现了这个: Should the Salt for a password Hash be "hashed" also?

盐的附加值是多少? 如果我编写 Web 服务,我可以在 3 次尝试失败后阻止每次登录。 前端没有人能够看到散列值。没有人可以使用蛮力(这可能只是 DoS,因为 3 次登录失败会阻止用户)。黑客需要访问数据库并查看散列密码。但如果他有,他会看到“盐”。

【问题讨论】:

  • 盐也存储在数据库中。
  • 使用盐之所以有用,是为了防止黑客使用预先计算的哈希值。例如,很容易获得前 100,000 个使用过的密码以及 md5 哈希值的列表。
  • MD5 坏了。无论有无盐,您都不能将其用于密码哈希。
  • @rdr:通常散列的想法是防止具有访问数据库的黑客窃取密码。
  • @rdr 盐阻止了彩虹表的使用。 (简而言之,如果password 哈希为12345,那么攻击者只需检查被盗数据库中的哈希12345 并在不使用盐时立即知道密码。但如果使用盐,那么存储的哈希值为passwordSALTSALTSALT,攻击者无法猜到(如果每个人都使用不同的盐)。)

标签: hash passwords salt


【解决方案1】:

Salt 用于防止黑客将密码散列反转为密码。所以在这里我们假设黑客以某种方式访问​​了数据库。

无盐

让我们首先假设没有盐的情况。在这种情况下,表格如下所示:

user | md5 password (first 6 chars)
-------------------------------
   1 | 1932ff
   2 | d3b073

(我们在这里使情况比现实更简单)

黑客当然想知道d3b0731932ff背后的密码是什么。散列函数是单向的,因为我们可以非常快速地散列密码,但是在猜测大量密码之后,如果它是一个很好的散列函数,那么取消散列会花费很长时间密码。

因此,轻松检索d3b073 背后的可能密码的希望并不大。但是我们可以很容易地找到 100'000 个最流行密码的列表,并计算所有这些密码的 MD5 哈希值。这样的列表可能如下所示:

password | md5 (first 6 characters)
--------------------------------------------
foo      | d3b073
bar      | c157a7

显然用户2 已使用foo 作为密码。我们不知道用户1 的密码(但我们知道它不是foobar)。

现在的重点是,我们可以构造这样的表一次,然后用它来破解所有用户的所有密码。为 100,000 个密码构建这样的表可能需要几个小时,但我们可以轻松检索所有密码。所以黑客可以构建(或下载)这样的表(有更有效的方法,例如使用 彩虹表),然后在他/她每次入侵网站时使用它,然后获取密码所有用户。

加盐

如果我们使用盐渍,表格可能如下所示:

user | salt   | hashed password
-------------------------------
   1 | a91f40 | 1a604e
   2 | c2a67c | b36232

所以这里如果用户2的密码是foo,那么我们计算fooc2a67c的哈希值(或者我们用另一种方式将盐和密码结合起来)并将其存储到数据库中。

关键是很难猜出密码,因为b36232 不是foo 的哈希值,而是fooc2a67c 的哈希值,而且salt 通常是(伪)随机的。我们当然可以再次构造最流行的 100'000 密码,并在其后附加盐 c2a67c,但由于我们无法提前知道 salt,因此我们不能只创建一次此表。即使我们很幸运并且已经为 salt c2a67c 构建了表,它也无法帮助我们破解用户 1 的密码,因为用户 1 有不同的 salt。

因此,解决此问题的唯一方法是为每个用户构建一个反向哈希查找表。由于构建一次这样的表通常非常昂贵,因此为每个用户计算这样的表并不容易。

我们当然可能决定计算所有可能盐的所有哈希值,例如:

password  | md5 (first 6 characters)
---------------------------------------------
foo000000 | 367390
foo000001 | eca8ea
foo000002 | 6eb7bf
foo000003 | 7906b1
foo000004 | 0e9f0c
foo000005 | 0bfb11
...       | ...

但正如您所见,这种桌子的大小会变得非常大。此外,这将需要数千年的时间。即使我们只添加一个十六进制字符作为盐,表格的大小也会缩放 16 倍。是的,有一些技术可以减少此类表的时间和空间,但是通过增加“密码空间”,破解密码的问题肯定会变得更加困难。此外,盐通常是大量的字符(或字节),这使得它比仅仅 16 倍更难。

salt 基本上是扩大密码空间的一种方式。即使您在两个网站上输入相同的密码,网站的个人盐值(几乎可以肯定)是唯一的,因此哈希值也将是唯一的。

【讨论】:

  • 很好的解释。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-01-24
  • 2015-07-19
  • 2014-05-03
  • 2010-11-30
  • 2016-04-09
  • 1970-01-01
  • 2013-02-05
  • 2012-07-05
相关资源
最近更新 更多