我该使用哪种算法将密码哈希到我的数据库中?

23

有没有什么东西是不容易被轻易破解的?


11
未来读者请注意:这份信息已经过时且存在风险。请访问IT安全堆栈交换网站上的问题“Do any security experts recommend bcrypt for password storage?”(http://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage/6415#6415)以获取最新信息。 - Brendan Long
11个回答

46

这个2008年的回答现在已经严重过时了。 SHA(所有变种)现在可以轻松破解,现在最好的做法是(截至2013年1月)使用一个密钥伸展哈希(例如PBKDF2)或理想情况下使用内存密集型加密(例如Bcrypt),并添加每个用户的盐。

点2、3和4仍然值得关注。

有关更多信息,请参见IT Security SE网站


原始2008年的回答:

  1. 使用经过验证的算法。SHA-256在数据库中使用64个字符,但在该列上建立索引后,这不是问题,并且它是一种经过验证的哈希,比MD5和SHA-1更可靠。它也作为标准安全套件的一部分在大多数语言中实现。但是如果您使用SHA-1也不要感到难过。

  2. 不要只散列密码,还要将其他信息放入其中。通常使用“用户名:密码:salt”的哈希值或类似哈希值,而不仅仅是密码,但是如果您玩弄此类操作,则使其更难攻击字典。

  3. 安全是一个艰难的领域,不要认为您可以发明自己的算法和协议。

  4. 不要编写类似于“[AddUser] GeorgeBush:Rep4Lyfe:ASOIJNTY的哈希值为xyz”这样的日志


7
发布时可能准确,但现在强烈建议不要使用SHA-1。 - Brian
3
这个回答在当时是准确的,但是云处理能力意味着重型暴力攻击现在变得很便宜。 SHA-1和MD5现在可以轻松破解。现在至少应该使用SHA-256,并始终添加足够大的盐。如果需要未来的保护,建议考虑使用像bcrypt或scrypt这样特意缓慢且需要大量处理器的哈希函数。 - Keith
2
令人震惊的是,如此短的时间内,由于暴力攻击技术的提高,曾被认为安全的算法现在被视为脆弱。 - JeeBee
实际上,当这篇文章写出来时,这已经是错误的建议了。密码哈希方案已经使用工作因素数十年了!以Unix crypt为例。 - Erwan Legrand

32

密码学和密码存储的第一条规则是“不要自己发明”,但如果你必须这样做,以下是维护任何安全性相似度所需的最低限度:

基本准则:

  1. 永远不要存储明文密码(这意味着您也不能显示或传输它)。
  2. 永远不要在未加密的线路上传输密码的存储表示(无论是明文、编码还是哈希)。
  3. 速度是你的敌人。
  4. 随着硬件和密码分析的提高,定期重新分析和改进你的过程
  5. 密码和过程只是解决方案的非常小的部分。
  6. 失败点包括:存储、客户端、传输、处理、用户、法律授权、入侵和管理员。

步骤:

  1. 强制执行合理的最低密码要求。
  2. 经常更换密码。
  3. 使用尽可能强的哈希算法-建议使用SHA-256
  4. 将密码与一个固定盐相结合(对于整个数据库相同)。
  5. 将上一步骤的结果与唯一盐相结合(可能是用户名、记录ID、GUID、长随机数等),并存储和附加到此记录。
  6. 多次运行哈希算法-如1000+次。理想情况下,每次都包含不同的盐,并与之前的哈希不同。速度是你的敌人,多次迭代会减慢速度。每隔一段时间加倍迭代次数(这需要捕获一个新的哈希-在下次更改密码时完成)。

哦,如果你没有运行SSL或其他安全线路,请不要允许密码以明文形式传输。而且如果您只是将客户端的最终哈希与您存储的哈希进行比较,则也不要以明文形式传输。您需要向客户端发送一个一次性数字(nonce),并要求他们使用上述步骤生成的哈希与其生成的哈希一起对其进行哈希,然后将其发送给您。在服务器端,您运行相同的过程,并查看两个一次性散列是否匹配。然后处理掉它们。这里有一种更好的方法,但这是最简单的方法。


为什么要使用站点范围内的盐和用户唯一盐?单个大的随机盐值不足以吗? - Jason Fritcher
2
一个单一的盐(任何大小)意味着,如果他们生成了一张彩虹表(哈希词典),那么每个数据库用户都可以使用它,因此他们很可能更快地找到匹配项。如果每个用户都有不同的盐,则意味着需要为每个用户生成新的查找表。 - Jim McKeeth
我理解为什么对于所有用户只使用一个盐值是不好的。我想了解在使用单个用户唯一盐值似乎已经足够的情况下,为什么要使用单个站点范围盐值加上用户唯一盐值的想法背后的原因。 - Jason Fritcher
如果您将用户名或其他弱盐用作用户特定的盐,那么额外的站点范围内的盐就变得更加重要了。例如,如果用户在另一个站点上具有相同的用户名和密码,则两个站点上的哈希值将相同。除此之外,它只是一个渐进式的改进。 - Jim McKeeth
随机盐是最好的。每当用户更改/创建密码时都要更改它们。您可以将额外的3-4个字符存储在与密码哈希相同的字段中,例如使用“:”分隔它们。因此,您的字段从aabbccddeeaabbccddeeaabbccddeeaabbccddee变为sLt:fb1337ce1afb1337ce1afb1337ce1afb1337ce1a。如果您想要交换两个子字段的顺序,则可以这样做,但关键是它很容易解析,而且可以大幅提高安全性。 - maxwellb

17

这是一个.NET实现的例子: http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx - Yaakov Ellis

8
上述算法是具有密码学安全性的哈希算法(但今天不认为MD5是安全的)。
然而,还有一些算法是专门用于从密码派生密钥的。这些是key derivation functions。它们被设计用于对称密码,但也适用于存储密码。例如,PBKDF2使用盐、大量迭代和一个好的哈希函数。如果您有一个实现它的库(如.NET),我认为您应该考虑使用它。

我认为PBKDF有很好的用途,但如果您正在实现具有密码保护的服务器应用程序,则需要在密码传输之前对其进行转换。通常,PBKDF将用于生成密钥,例如对称加密。受密码保护的论坛通常需要使用价格便宜的算法,并具有相当好的冲突防止能力,因为变换的结果本质上是要与数据库进行比较的“密码”。增加随机性和减少碰撞的可能性是提高安全性的方法。随机盐+良好的哈希应该可以解决问题。 - maxwellb
@mpbloch:在密码通过网络传输之前,您无法对其进行转换。您可以使用SSL来保护它。由于彩虹表攻击,您需要对密码进行哈希处理。而且只有在服务器上对其进行哈希处理才是可能的。 - KovBal

6

在哈希密码值中添加一个唯一的盐(将盐值存储在数据库中)。当使用唯一的盐时,使用比SHA1或MD5更安全的算法并不是必要的(此时它只是渐进式改进,而使用盐则是重大的改进)。


5

使用像MD5或SHA1这样的强加密哈希函数,但确保您使用良好的,否则您将容易受到彩虹表攻击。


5

2013年1月更新

原始答案发布于2008年,过去5年中情况有所变化。云计算和强大的并行处理图形卡的普及意味着,使用MD5或SHA1哈希的密码长度为8或9个字符现在很容易被破解。

现在必须使用较长的盐,并且需要像SHA512这样更强的加密方式。

然而,所有SHA变体哈希都是为通信加密而设计的 - 来回传递的消息每条消息都加密了,因此它们被设计成快速

在密码哈希世界中,这种设计是一个很大的劣势,因为哈希生成得越快,生成大量哈希所需的时间就越少。像SHA512这样的快速哈希可以每秒生成数百万甚至数十亿次。加入廉价的并行处理,每个可能的密码排列组合都成为了绝对必要的。

键拉伸是应对这种情况的一种方法。键拉伸算法(如PBKDF2)将快速哈希(如SHA512)应用于数千次,通常导致哈希生成约需要1/5秒左右。登录的人不会注意到,但如果您只能每秒生成5个哈希,暴力攻击就会更加困难。

其次,始终应该有一个针对每个用户的随机盐。这可以随机生成为哈希的前n个字节(然后将其剥离并添加到要检查的密码文本中,以便构建要比较的哈希)或作为额外的DB列。

所以:

我应该使用什么算法将密码哈希到我的数据库中?

  • 键拉伸以减慢哈希生成速度。我可能会选择PBKDF2。

  • 针对每个用户的盐意味着每个用户都需要一次新的攻击,并且需要一些工作来确定如何获取盐。

计算能力和可用性呈指数级增长 - 很可能这些规则在另外4年内会再次改变。如果您需要具有未来保障的安全性,我建议调查bcrypt / scrypt样式的哈希 - 这些哈希采用较慢的键拉伸算法,并添加了一步使用大量RAM来生成哈希。使用这么多RAM会降低廉价并行处理器的效果。

原始答案(2008年9月发布,保留以便评论有意义)

MD5 +盐或SHA1 +盐不是“轻松破解”的 - 大多数黑客都依赖于巨大的彩虹表,而这些表在使用盐后变得不太有用 [更新,现在它们]

MD5 +盐是一个相对较弱的选项,但不会很容易被破解 [更新,现在它非常容易被破解]

SHA2可以达到512位 - 这将非常难以使用现成的工具破解[更新,现在容易破解长度为9个字符的密码] - 虽然我相信某些军事掩体中可能有一台Cray可以做到这一点[你现在可以从亚马逊租用这台'Cray']


SHA2的速度非常快。绝对比AES快得多...即使对大量数据进行多次哈希,我也认为性能不太可能受到任何显著的降低。 - AviD

1

1

使用MD5或SHA与每个条目随机生成的盐值相结合


0

所有哈希算法都容易受到"字典攻击"的威胁。攻击者会拥有一个非常大的可能密码字典,然后对其中所有密码进行哈希运算。接着,他们会查看这些哈希值是否与他们想要解密的密码的哈希值匹配。这种技术可以轻松测试数百万个密码。因此,您需要避免使用任何可能被预测的密码。

但是,如果您愿意承担字典攻击的威胁,MD5和SHA1都足够安全。SHA1更加安全,但对于大多数应用程序来说,这并没有显著的改进。


如果你使用<a href="http://en.wikipedia.org/wiki/Salt_(cryptography)">salt</a>,将会让字典攻击变得更加困难。 - Kip
“更加困难”?适当的盐值可以使字典攻击变得不可能,因为地球上没有足够的存储空间。 - erickson
3
盐并不能抵御字典攻击,但可以防止彩虹表攻击。这两个概念非常不同。 - KovBal
+1 给 KovBal。此外,使用 k 位哈希函数进行的“字典攻击”可以针对所有可能的密码进行2^k次尝试。使用非字母数字(基本上)的字母表已经将搜索空间增加了指数级别。将“提供包含最多8个字符的字母数字密码”与“160位整数”进行比较,哪个字典更大? - maxwellb
盐是为了打败字典攻击。 彩虹表是字典攻击的一种特定形式,而不是不同的概念。 - erickson

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