使用真随机盐或用户名盐加胡椒粉进行密码哈希?

5
考虑以下两种方法:
hashedPassword = hash(trulyRandomSalt + password)

哈希密码和真正的随机盐在数据库中存储。

hashedPassword = hash(applicationConstantPepper + uniqueUserName + password)

哈希密码和唯一的用户名存储在数据库中,应用程序常量辣椒存储在应用程序配置中。这里,唯一的用户名充当盐,通常是电子邮件地址。

我阅读了问题链接,其中包含很多有用的信息,但没有提到应用程序常量辣椒值以及如何使用用户名作为盐将如何改进安全性。

我一直使用方法一,即使用32位加密随机盐。然而,我刚刚看到另一个应用程序中使用了方法二。我对方法二的第一个问题是它将用户名与哈希绑定在一起,因此用户名不能更改而不重新生成哈希。

方法二存在哪些安全问题?哪种方法是最好的?

4个回答

1
考虑以下两种方法:
第一种方法很糟糕,因为它允许攻击者获取您的哈希值并使用类似 oclHashcat 的工具每月进行数万亿或数千万亿次的尝试,而第二种方法更可怕,因为如果攻击者在获得您的密码之前获取了 applicationConstantPepper 和用户名,他们可以在获取您的密码时预先计算尝试次数。
请阅读如何安全地哈希密码?,其中Thomas Pornin指出:“要使加入pepper变得真正适用,您需要处于一个特殊的设置中,那里有比带有硬盘的个人电脑更多的东西;您需要一个HSM。” 请阅读整篇文章以了解上下文,但其要点是:
  • 使用PBKDF2(也称为RFC2898和PKCS#5v2),BCrypt或SCrypt。
  • 不要使用单个哈希算法的一次传递,无论你的调味料有多好。
  • 使用8-16个字节的加密随机盐。
  • 使用尽可能高的迭代次数/工作因子,以使您的机器在峰值负载下处理时不会引起用户抱怨。
  • 对于PBKDF2,不要请求或使用比哈希函数的本机大小更多的输出字节。
    • SHA-1 20字节
    • SHA-224 28字节
    • SHA-256 32字节
    • SHA-384 48字节
    • SHA-512 64字节
  • 如果您使用的是64位系统,请考虑使用PBKDF2-HMAC-SHA-384或PBKDF2-HMAC-SHA-512,这将减少攻击者使用2014年版GPU时的优势。
如果您仍然喜欢pepper的概念,请阅读密码哈希添加盐和胡椒粉还是只加盐?,特别是Thomas Porrin的回答。

Thomas Porin 没有注意到一些微妙的细节(或者他知道但是过于笼统)。 - jww
有哪些特别的要点,为什么不在评论或编辑中建议它们,以便将其包含在这样一个受欢迎的问题和答案中呢? - Anti-weakpasswords
"...为什么不在评论或编辑中建议它们呢?" - 这不是我感兴趣的战斗。 - jww
@noloader,如果有与我的回答或原问题有关的引用或摘录,您能否在此提供一下参考? - Anti-weakpasswords
我认为盐(和胡椒粉)被视为公共参数。没有必要将它们存储在HSM中。然而,存储HMAC密钥是适当的。HMAC具有可证明的安全属性(如PRF和PRP安全性概念);而无键哈希与它们不等价。就像我说的,有一些微妙的点不太对。 - jww
谢谢您指引我正确的方向。我会研究PBKDF2、BCrypt和SCrypt。 - Jason Eades

1
考虑以下两种方法...... 两种方法都不是特别好......

方法二存在哪些安全问题?

OWASP 的 John Steven 提供了有关密码哈希和存储的较好的撰写,他带您了解各种威胁,并解释了为什么要以某种方式进行操作。请参见:


哪种方法是最好的使用方法?

hashedPassword = hash(applicationConstantPepper + uniqueUserName + password) 不提供语义安全性。也就是说,使用常量pepper和用户名,对手可以判断oracle是否回答了随机答案或真实答案。

hashedPassword = hash(trulyRandomSalt + password) 可能等同于或略优于其他建议的方法。每个用户的随机salt具有许多理想的属性。但是它也可以改进。


最后,为什么要重复造轮子呢?前往Openwall的可移植PHP密码哈希(phpass)并使用它。它是由John the Ripper的作者编写的。Solar Designer跟上了密码破解技术的最新进展,因此该库在实践中可能非常有用。

你说这两个输入都不是很好。那么什么样的输入会更适合哈希函数呢? - Rick
@Rick - 你可能想要放弃使用哈希,而是使用一个带密钥的哈希。这个带密钥的哈希是HMAC。你也可能想要迭代输入而不是使用一次迭代。应用程序特定的pepper可能很好。从更大的角度来看,这个问题不适合在Stack Overflow上讨论。安全目标需要被说明,并且需要进行分析。询问其他程序员他们做什么会导致缺乏上下文和分析的无用答案。你可能应该阅读约翰·史蒂文斯的材料。 - jww
谢谢,我明白你的观点,确实需要定义安全上下文才能得到有用的答案。对于密码哈希,我认为一旦你有了唯一的盐值,长度扩展攻击就没有任何用处,因此迭代哈希和键控哈希之间的差异将是微不足道的。除了保护免受长度扩展攻击之外,你是否知道HMAC相对于迭代哈希的另一个优点? - Rick

1
除了Anti-weakpasswords的回答外,我想指出,盐(salt)和胡椒(pepper)都有其用途。如果您同时应用两者,则使用随机盐并将其存储在数据库中(而不是派生的盐),之后使用服务器端密钥(胡椒)对密码哈希进行加密。
我写了一个tutorial,其中更详细地解释了使用胡椒的利弊。使用服务器端密钥是一种优势,即使无法完全保护该密钥。

0

这两种方法大致相等,只要你使用了一个好的哈希函数(请参见其他答案)。

使用用户名的问题在于用户名可以被重复使用。如果您不包括应用程序特定前缀,则可能会出现巨大问题,因为该用户名可能已经在许多地方使用,因此可能已经存在一个不错的彩虹表。

“pepper”有助于缓解这个问题,因为它要求彩虹表针对您的应用程序进行特定设置。现在,仅当用户频繁更改密码时才会成为问题,因为攻击者现在可以通过生成一个彩虹表来获取所有旧密码,而不是每次搜索仅获取一个密码。在我看来,这几乎是可以忽略不计的缺点,因为

  1. 大多数人不会频繁更改密码
  2. 攻击者仍然必须访问每个他们想要破解的密码的哈希值,因此对于一次性数据库泄漏,没有任何区别。
  3. 任何经常更改密码的人都不太可能在其他地方重复使用相同的密码,因此获得的额外密码将不太有用。

总体而言,从攻击者的角度来看,如果与pepper结合使用使它们变得独特,那么从目标使用用户名作为盐的角度来看,收益不大。


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