密码加盐 101

26

请问有谁能帮我理解盐值是如何工作的吗?

目前我了解到以下内容:

  1. 验证密码
  2. 生成一个随机字符串
  3. 将密码和随机字符串进行哈希运算并连接起来,然后将它们存储在密码字段中...

我们如何存储盐值,或者在用户登录时知道它是什么呢?我们是否将其存储在单独的字段中?如果我们不这样做,应用程序如何找出盐值是什么?如果我们确实存储了它,那不是完全违背了盐值的作用吗?


找到了一个更好的“完全重复”的问题:https://dev59.com/pXRC5IYBdhLWcg3wD83r - George Stocker
5个回答

37

在哈希之前,将盐与密码组合。将密码和盐值清晰的值连接在一起,然后对生成的字符串进行哈希。这保证了即使两个人拥有相同的密码,也会产生不同的哈希结果。(同时使得使用彩虹表等字典攻击更加困难)。

然后,将盐以原始/明文格式与哈希结果一起存储。稍后,当您想要验证密码时,需要再次执行原始过程。将记录中的盐与用户提供的密码组合,哈希结果,比较哈希。

您可能已经知道这一点了,但很重要的是记住。盐必须每次随机生成。它必须对于每个受保护的哈希都不同。通常使用 RNG 生成盐。

例如:
用户密码:"mypassword"
随机盐:"abcdefg12345"
生成的明文:"mypassword:abcdefg12345" (如何组合它们取决于您,只要每次使用相同的组合格式即可)。
对生成的明文进行哈希:"基于算法的某些标准长度哈希"

现在在您的数据库中,您将存储使用的哈希和盐。我见过两种方法:

方法1:
字段1-盐="abcdefg12345"
字段2-密码哈希="基于算法的某些标准长度哈希"

方法2:
字段1-密码哈希="abcdefg12345:基于算法的某些标准长度哈希"

在任一种情况下,您都必须从数据库中加载盐和密码哈希,并重新执行哈希以进行比较。


12
salt <- random
hash <- hash(password + salt)
store hash:salt

稍后

input password
look up hash:salt
hash(password+salt)
compare with stored hash

明白了吗?


3
盐值的目的是为了防止字典攻击。与其创建一个哈希密码字典,然后简单地在各处查找匹配项,不如强制攻击者为每个唯一的盐重新计算所有哈希值。这样,即使密码数据库落入错误的人手中也没有关系,因为对手面临的是一个计算上难以实现的问题。 - Ian
Ian,盐也需要进行哈希处理吗? - Mohamad
2
@Mel:由于盐通常是一堆随机比特,对它进行哈希毫无意义。 - jpalecek
2
哈希不可逆,你需要知道实际的盐值,所以不要进行哈希。盐的目的是使彩虹表攻击无效。它需要对每个用户都不同,以使生成新的彩虹表变得不那么有价值。为了达到这个目的,它不需要保密,但如果它是秘密或者有点隐藏,那么它将使生成表格变得更困难。例如,真正的盐可以是 f(salt),其中 f() 在你的代码中某个地方。 - Lou Franco
@Lou Franco:实际上,哈希的目的是避免相同的明文散列总是相同的(因此具有相同密码的两个用户将具有相同的散列密码,攻击者可以为常见密码预先计算散列值)。 彩虹表出现得更晚。 - ninjalj
1
@Mohamad,每次调用哈希函数时,你都将盐值包含在输入中。然而,你也会单独存储盐值,以明文格式保存,这样你就有一些机会来测试密码。基本上,“盐”存在的目的是将单个哈希函数转化为多个哈希函数。因此,你需要确切地记住使用哪个哈希函数与给定密码配对(这就是为什么你以明文形式保存盐值),但你不希望对于多个密码使用相同的哈希函数(这就是为什么盐值是随机的)。 - Ian

4
根据《实用密码学》(Neils Ferguson和Bruce Schneier)的说法,为了获得最大的安全性,您应该使用加盐、拉伸的哈希算法。
x[0] := 0
x[i] := h(x[i-1] || p || s)  for i = 1, ..., r
K := x[r]

where
   h is the hash (SHA-1, SHA-256, etc.)
   K is the generated hashed password
   p is the plaintext password
   r is the number of rounds
   s is the randomly generated salt
   || is the concatenation operator

盐值是与加密密码一起存储的随机数,不需要保密。

拉伸是多次执行哈希以使攻击者难以测试多个密码组合的行为。应选择r,使计算在用户计算机上大约需要200-1000毫秒。随着计算机速度的提高,可能需要增加r


4
我们如何存储盐,或者在用户登录时如何知道它是什么?我们将其存储在自己的字段中吗?
是的。
如果我们确实存储它,那不会完全打败目的吗?
不会。盐的目的并非保密,而仅仅是为了防止攻击者将计算彩虹表的成本分摊到世界上所有站点(不使用盐)或您网站上的所有用户(单个盐用于所有用户)。

1
如果你使用一个众所周知的哈希算法,有人可能已经有一个使用该算法散列的许多可能密码的列表,并将该列表中的项与他们想要破解的散列密码进行比较(字典攻击)。 如果在散列之前对所有密码进行“盐”处理,这些字典就无用了,因为它们必须使用你的盐来创建。

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