密码哈希、盐和哈希值的存储

39
假设您可以自由决定如何在DBMS中存储哈希密码。这种方案存在明显的弱点吗?
创建存储在DBMS中的哈希值,请执行以下操作:
- 作为盐的一部分,使用唯一于DBMS服务器实例的值, - 使用用户名作为盐的第二部分, - 创建盐与实际密码的串联, - 使用SHA-256算法对整个字符串进行哈希, - 并将结果存储在DBMS中。
这意味着任何想要制造冲突的人都必须为每个用户名和每个DBMS服务器实例单独完成工作。我计划使实际哈希机制略微灵活,以允许使用仍在开发中的新NIST标准哈希算法(SHA-3)。
“唯一于DBMS服务器实例的值”不需要保密 - 尽管不会轻易透露。目的是确保如果某人在不同的DBMS服务器实例中使用相同的密码,则记录的哈希值将不同。同样,用户名不需要保密 - 只有密码本身需要保密。
将密码放在第一位,将用户名和“唯一值”放在第二位,或者对三个数据源的排列进行任何其他排列,是否有任何优势?或者交错字符串呢?

我需要添加(并记录)一个随机的盐值(每个密码一个)来增加密码的安全性吗?(优点:用户可以重复使用密码,但是数据库中记录的哈希值很可能不同。缺点:必须记录盐值。我认为优点远大于缺点。)

相关的SO问题很多 - 这个列表可能不全:

我认为这些问题的答案支持了我的算法(尽管如果您仅使用随机盐,则“每个服务器的唯一值”和用户名组件就不那么重要)。


1
随机部分很重要,它可以防止预测攻击。 - Jacco
2
将用户名添加到盐中需要密码明文可用于重置密码哈希,如果您想更改用户名的话。如果这是个问题的话。 - blueshift
1
从下面所有的评论中,我没有看到关于盐应该放在哪里(之前还是之后)的答案?我想知道如果盐放在之前、之后或可能两者都放,是否更难对哈希进行暴力破解,或者它真的不重要放在哪里? - Jeach
2
@blueshift 我不是密码学家,但是...你能不能通过要求提供密码来更改用户名来绕过这个问题呢? - Blacklight Shining
@BlacklightShining:是的。 - blueshift
显示剩余3条评论
4个回答

31

盐只需要是随机和唯一的。它可以自由地被知道,因为它不会帮助攻击者。许多系统将明文盐存储在数据库中,位于散列密码的旁边。

盐有助于确保如果两个人(用户A和用户B)恰好共享相同的密码,则不会很明显。如果每个密码没有随机和唯一的盐,散列值将相同,很明显如果用户A的密码被破解,那么用户B必须具有相同的密码。

它还有助于防止攻击,其中一个散列值字典可以与已知密码进行匹配,例如 彩虹表攻击。

此外,使用内置“工作因素”的算法也意味着随着计算能力的增加,算法必须通过的工作量也可以增加。例如bcrypt。这意味着暴力攻击的经济变得不可行。假设创建已知哈希表变得更加困难,因为需要更长时间来创建它们;“工作因素”中的变化将意味着需要建立更多表。


5
盐值加密还可以保护我们免受基于彩虹表的攻击。 - Kane Wallmann
是的,正如我在其他答案的评论中所指出的那样,我的问题在编写时发生了变化,我意识到随机盐是必要的,但没有花时间反思它是否足够。将用户名添加到混合物中主要是为了延长哈希算法需要处理的数据长度,有助于保护短密码。这种额外保护的真实性,我不确定。 - Jonathan Leffler
13
这个回答是错误的。盐的目的 不是 为了让“共享密码不明显”。它的目的是使字典攻击更加困难。(允许像这样具有危险性的错误响应被标记为“答案”是该网站的致命设计缺陷。) - Glenn Maynard
3
我建议您阅读http://codahale.com/how-to-safely-store-a-password/以了解为什么您的答案存在安全隐患。简单来说,“暴力破解比您想象的要快”。拥有盐是必要的,没有它,人们可以使用预先计算好的查找表 - 但这并不足以保护使用弱密码的用户(大多数用户都是这样)。 - btilly
3
您提供的链接是纯粹的(危险的)无稽之谈。bcrypt并不能比给密码加盐更有效地防止暴力攻击。攻击者的目的是获取访问权限,因此他只需要暴力破解可能的密码,而不是散列值。bcrypt替代方案将计算开销转移到服务器上,因此只是浪费资源,没有其他作用。如果您使用了密码12345,并且我对该密码进行了暴力破解,无论您使用什么奇怪的计算密集型加密技术,您都会被入侵。随机盐就可以了,不要使用弱密码! - DeveloperChris
显示剩余4条评论

19

我认为你正在过度复杂化问题。

从问题开始:

  1. 你是在试图保护弱密码吗?
  2. 你是在试图减轻彩虹攻击的影响吗?

你提出的机制确实可以防止简单的彩虹攻击,因为即使用户A和用户B有相同的密码,散列后的密码也将不同。然而,这似乎是一种过于复杂的盐值方法。

  • 当你将数据库迁移到另一个服务器时会发生什么?
    • 如果可以更改每个数据库唯一的值,那么可以生成全局彩虹表;否则无法恢复数据库。

相反,我只会添加额外的列并存储真正的随机盐。这将防止任何类型的彩虹攻击。跨多个部署。

但这不会保护你免受暴力攻击。因此,如果你试图保护具有糟糕密码的用户,则需要寻找其他方法。例如,如果你的用户使用四位数密码,即使有盐和最新的哈希算法,它也可能在几秒钟内被破解。


1
我认为你可能是对的 - 当我写这个问题时,我意识到随机盐是必要的;我没有花时间注意到它也足够了。话虽如此,一个担忧是给哈希算法更多的数据来处理 - 用户名有一点帮助,盐也有。恢复到另一个DBMS服务器实例是一个合理的担忧 - 这是我没有考虑到的。在那种情况下,用户名和盐都可以,而用户名并不是百分之百必要的。谢谢。 - Jonathan Leffler

7

我认为你需要问自己:“通过将此过程变得比生成随机盐值并存储更复杂来获得什么好处?”你的算法越复杂,就越可能无意中引入漏洞。这可能会听起来有点讽刺,但我的意思是:你的应用程序有什么特别之处,需要一个新的高级密码哈希算法呢?


@Peter:不会冒犯 - 我明白你的意思。在我撰写时,“有何不同”的一个方面是“确保使用相同密码的不同服务器存储不同的密钥”。正如其他评论中所指出的,我在问题末尾意识到随机盐是必要的;我没有发现它是足够的。哈希中的额外数据有助于保护短和弱密码。我无法评估这样做对安全性有多大影响。 - Jonathan Leffler
继续:如果盐是一个8字节的整数,密码只有一个字母,那么SHA-256哈希算法真的足够保护它吗?如果用户名只有3个字符,而“服务器唯一”数据是一个32个字符随机确定(但固定)的字符串,这是否有助于保护数据——有44个字节的数据可以处理,而不仅仅是9个字节。这似乎应该更安全(9个字节可能会被彩虹攻击;44个字节可能不容易被攻击)。也许“服务器唯一”只需要是一个“固定的32字节字符串”... - Jonathan Leffler
继续(2):也许需要使用固定字符串将“盐加密码”填充到64字节(或32字节,或其他某个数字)?或者也许这只是一场大猎鹅活动;这真的无关紧要。 - Jonathan Leffler

6

为什么不给密码添加一个随机的盐并将两者组合进行哈希处理。然后将哈希值和盐连接成一个字节数组,并将其存储在数据库中?

随机盐的好处是用户可以随意更改用户名。盐不需要保密,因为它用于防止字典攻击。


2
+1 表示用户无法再更改其用户名。 - Sam Saffron
@pb:在这种情况下,我不希望用户更改他们的名称,谢谢。在某些情况下,这可能很有价值,但就这个应用程序而言,用户的名称是固定的(或者更准确地说,如果有人更改了他们的名称,他们将成为一个新的、不同的用户)。只使用随机盐和密码可能是可以的;我有点担心确保哈希算法有足够的材料来进行计算——这也是添加不止盐的原因之一。当我写这个问题时,我意识到随机盐是必要的;我没有注意到它也是足够的。 - Jonathan Leffler
用户仍然可以更改他们的用户名,但此时您必须重新计算其密码哈希值。另一方面,使用随机盐与使用非随机盐具有相同或更大的好处。 - wprl

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