我应该使用哪种算法将密码散列到数据库中?

时间:2020-03-06 14:33:24  来源:igfitidea点击:

有没有可以轻易破解的东西?

解决方案

MD5 / SHA1哈希都是不错的选择。 MD5比SHA1稍弱。

去年,CodingHorror上有一篇很棒的文章

http://www.codinghorror.com/blog/archives/000953.html

本文末尾的建议是BCrypt

MD5或者SHA结合每个条目随机生成的盐值

使用像MD5或者SHA1这样的强大的哈希散列函数,但请确保使用良好的盐,否则我们将容易受到彩虹表攻击。

所有哈希算法都容易受到"字典攻击"的攻击。这只是攻击者拥有大量可能的密码的字典的地方,它们会对所有密码进行哈希处理。然后,他们查看这些哈希中是否有任何一个与他们要解密的密码的哈希匹配。此技术可以轻松测试数百万个密码。这就是为什么我们需要避免使用任何可远程预测的密码的原因。

但是,如果我们愿意接受字典攻击的威胁,则MD5和SHA1都绰绰有余。 SHA1更安全,但是对于大多数应用程序来说,这确实不是一个重大改进。

This 2008 answer is now dangerously out of date. SHA (all variants) is now trivially breakable, and best practice is now (as of Jan 2013) to use a key-stretching hash (like PBKDF2) or ideally a RAM intensive one (like Bcrypt) and to add a per-user salt too. 
  
  Points 2, 3 and 4 are still worth paying attention to.
  
  See the IT Security SE site for more.

2008年原始答案:

  • 使用经过验证的算法。 SHA-256在数据库中使用64个字符,但是在列上有一个索引是没有问题的,并且它是经过验证的哈希,并且比MD5和SHA-1更可靠。作为标准安全套件的一部分,它还以大多数语言实现。但是,如果我们使用SHA-1,请不要感到难过。
  • 不要只是散列密码,还要在其中输入其他信息。我们经常使用" username:password:salt"或者类似名称的哈希值,而不只是密码,但是如果我们使用此哈希值,则将更难于进行字典攻击。
  • 安全性是一个艰巨的领域,不要以为自己可以发明自己的算法和协议。
  • 不要写像" [AddUser] GeorgeBush的哈希:Rep4Lyfe:ASOIJNTY是xyz"这样的日志

将唯一的盐添加到哈希密码值中(将盐值存储在数据库中)。当使用唯一的盐时,实际上不需要使用比SHA1或者MD5更安全的算法的好处(在那一点上,它是一种增量的改进,而使用盐是一项重大的改进)。

2013年1月更新

最初的答案是从2008年开始的,在最近5年中情况有所变化。云计算和强大的并行处理器图形卡已经可以使用,这意味着散列为MD5或者SHA1的最多8或者9个字符的密码现在可以轻易破解。

现在必须加长盐,像SHA512一样坚硬。

但是,所有SHA变体散列均设计用于在每个消息都经过加密的情况下来回通信加密消息,因此,它们被设计为快速的。

在密码哈希世界中,此设计有一个很大的缺点,因为生成哈希越快,生成大量哈希所需的时间就越少。

像SHA512这样的快速哈希可以每秒生成数百万甚至数十亿次。进行廉价的并行处理,密码的所有可能排列成为绝对必要的。

密钥拉伸是解决此问题的一种方法。密钥拉伸算法(如PBKDF2)数千次应用更快的哈希(如SHA512),通常导致哈希生成花费1/5左右的时间。有人登录不会引起注意,但是如果我们每秒只能生成5个哈希,则蛮力攻击要困难得多。

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

所以:

What algorithm should I use to hash passwords into my database?
  • 密钥拉伸可减慢哈希生成。我可能会选择PBKDF2.
  • 每位用户的盐分意味着每位用户的新攻击,还有一些工作在弄清楚如何获得盐分。

计算能力和可用性呈指数增长,这些规则将在未来4年内再次发生变化。如果我们需要面向未来的安全性,我将研究bcrypt / scrypt样式的哈希,这些哈希采用较慢的密钥拉伸算法,并添加了一个使用大量RAM生成哈希的步骤。使用大量RAM会降低廉价并行处理器的效率。

原始的2008年9月(留在左边,这样的注释才有意义)

MD5 + salt或者SHA1 + salt并不是"易碎的",大多数hack依赖于巨大的彩虹表,而这些盐在使用"​​ [update,now now are]"盐后变得不再有用。

MD5 +盐是一个相对较弱的选项,但它不会轻易被破坏[[update,现在很容易被破坏]。

SHA2一直上升到512,使用现成的工具包" [更新,现在很容易达到9个字符的密码]"几乎是不可能破解的,尽管我确定某个地方的军用掩体中有Cray可以做它我们现在可以从亚马逊租用这个'Cray'

前面提到的算法是加密安全的哈希算法(但是,今天MD5不被认为是安全的)。

但是,有些算法是专门为从密码派生密钥而创建的。这些是关键的推导函数。它们是设计用于对称密码的,但是它们也很适合存储密码。例如,PBKDF2使用盐,大量迭代和良好的哈希函数。如果我们有一个库,它是由什么实现的(例如.NET),我认为我们应该考虑一下。

密码和密码存储的首要原则是"不要自己发明",但如果必须这样做,则必须采取最低限度的措施以确保具有类似的安全性:

基本规则:

  • 永远不要存储纯文本密码(这意味着我们也永远不会显示或者传输该密码。)
  • 切勿在不安全的行(纯文本,编码的或者散列的)上传输存储的密码表示形式。
  • 速度是你的敌人。
  • 随着硬件和密码分析的改进,定期重新分析和改进过程。
  • 密码学和过程只是解决方案的一小部分。
  • 故障点包括:存储,客户端,传输,处理,用户,法律保证书,入侵和管理员。

脚步:

  • 强制执行一些合理的最低密码要求。
  • 经常更改密码。
  • 使用我们可以获得的最强哈希值-建议在此处使用SHA-256.
  • 将密码与固定的盐结合使用(与整个数据库相同)。
  • 将上一步的结果与存储并添加到该记录的唯一盐(可能是用户名,记录ID,GUID,长随机数等)结合起来。
  • 多次运行哈希算法-超过1000次。理想情况下,每次与以前的哈希一起包含不同的盐。速度是敌人,多次迭代会降低速度。经常使迭代次数翻倍(这需要捕获新的哈希-下次更改密码时进行。)

哦,除非我们正在运行SSL或者其他一些线路安全性,否则请不要以纯文本形式传输密码。而且,如果我们仅将来自客户端的最终哈希值与存储的哈希值进行比较,则也不允许以纯文本形式传输该哈希值。我们需要向客户端发送一个随机数(使用一次的数字),并使其与生成的散列(使用上述步骤)进行散列,然后再将其发送给我们。在服务器端,我们运行相同的过程,并查看两个一次性哈希是否匹配。然后处置它们。有一种更好的方法,但这是最简单的方法。