【问题标题】:What algorithm should I use to hash passwords into my database? [duplicate]我应该使用什么算法将密码散列到我的数据库中? [复制]
【发布时间】:2010-09-12 02:44:56
【问题描述】:

是否有任何东西不易损坏?

【问题讨论】:

标签: security encryption passwords hash


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    CodingHorror 去年有 a great article on this。文末推荐bcrypt.

    【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      使用强大的加密哈希函数,如 MD5 或 SHA1,但请确保使用良好的 salt,否则您将容易受到 rainbow table 攻击。

      【讨论】:

        【解决方案5】:

        所有散列算法都容易受到“字典攻击”的影响。这只是攻击者拥有一个非常大的可能密码字典的地方,并且他们对所有密码进行了哈希处理。然后,他们查看这些哈希中是否有任何与他们要解密的密码的哈希匹配。这种技术可以轻松测试数百万个密码。这就是为什么您需要避免使用任何可远程预测的密码。

        但是,如果您愿意接受字典攻击的威胁,MD5 和 SHA1 就足够了。 SHA1 更安全,但对于大多数应用程序来说,这确实不是一个显着的改进。

        【讨论】:

        • 如果你使用 en.wikipedia.org/wiki/Salt_(cryptography)">salt</a> 你会让字典攻击变得更加困难。
        • “更难”?适当的盐使字典攻击变得不可能,因为地球上没有足够的存储空间。
        • Salt 不是针对字典攻击,而是针对彩虹表。这两个概念非常不同。
        • +1 到 KovBal。此外,使用 k 位散列函数,针对所有可能密码的“字典攻击”是 2^k 个“单词”。使用非字母数字(基本上)字母表已经成倍地增加了搜索空间。将“提供最多 8 个字符的字母数字密码”与“160 位整数”进行比较。哪个有更大的字典?
        • Salt 是用来击败字典攻击的。彩虹表是字典攻击的一种特定形式。这不是一个不同的概念。
        【解决方案6】:

        这个 2008 年的答案现在已经过时了。 SHA(所有变体)现在很容易被破解,现在(截至 2013 年 1 月)最佳实践是使用密钥拉伸哈希(如PBKDF2) 或理想情况下是 RAM 密集型的(如 Bcrypt),并添加每个用户的盐。

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

        请参阅IT Security SE site 了解更多信息。


        2008 年原始答案:

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

        2. 不要只是散列密码,还要将其他信息放入其中。您经常使用“username:password:salt”或类似的哈希值,而不仅仅是密码,但如果您使用它,那么您会更难进行字典攻击。

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

        4. 不要写像“[AddUser] Hash of GeorgeBush:Rep4Lyfe:ASOIJNTY is xyz”这样的日志

        【讨论】:

        • 虽然在发布时可能准确,但现在强烈建议不要使用 SHA-1。
        • 这个答案在当时是准确的,但云处理能力意味着重型蛮力攻击现在很便宜。 SHA-1 和 MD5 现在很容易破解。这些天我会使用最少的 SHA-256 并且总是添加相当大的盐。如果您需要未来的证明,我会考虑故意使用缓慢且处理器密集型的哈希,例如 bcrypt 或 scrypt。
        • 令人震惊的是,如此短的时间如何导致被认为是安全的算法仅仅由于暴力攻击改进而被认为是弱的。
        • 实际上,在写这篇文章的时候,这已经是一个糟糕的建议了。密码哈希方案几十年来一直使用工作因子!以 Unix crypt 为例。
        【解决方案7】:

        unique salt 添加到哈希密码值(将盐值存储在数据库中)。当unique salt is used 使用比 SHA1 或 MD5 更安全的算法的好处时,实际上并没有必要(此时它是一种渐进式改进,而使用盐是一项巨大的改进)。

        【讨论】:

          【解决方案8】:

          2013 年 1 月更新

          最初的答案是 2008 年,过去 5 年发生了一些变化。云计算和强大的并行处理器图形卡的现成可用性意味着密码最多 8 或 9 个字符散列为 MD5 或 SHA1 现在可以轻松破解。

          现在必须使用长盐,就像 SHA512 这样更坚固的盐。

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

          在密码散列世界中,这种设计是一个很大的缺点,因为生成散列的速度越快,生成大量散列所需的时间就越少。

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

          按键拉伸是解决此问题的一种方法。密钥拉伸算法(如 PBKDF2)应用更快的哈希(如 SHA512)数千次,通常会导致哈希生成需要 1/5 秒左右。登录的人不会注意到,但如果你每秒只能生成 5 个哈希值,那么暴力攻击就更难了。

          其次,应该始终是每个用户的随机盐。这可以随机生成为散列的前 n 个字节(然后将其剥离并添加到密码文本中以在构建散列进行比较之前进行检查)或作为额外的 DB 列。

          所以:

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

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

          • Per-user salt 意味着每个用户的新攻击,以及一些工作来弄清楚如何获取 salt。

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

          原件 2008 年 9 月(留下来让 cmets 有意义)

          MD5+salt 或 SHA1+salt 不是“容易破解的”——大多数 hack 依赖于巨大的彩虹表,而使用 salt [update, now they are] 时,这些就变得不那么有用了。

          MD5+salt 是一个相对较弱的选项,但不会轻易被破解[update, now it is very easy to break]

          SHA2 一直到 512 - 使用现成的工具包 [update, pretty easy up to 9 char passwords now] 几乎不可能破解 - 虽然我确信某个军事掩体中的某个 Cray 可以做到这一点 [You can now rent this 'Cray' from Amazon]

          【讨论】:

          • SHA2 速度惊人。甚至比 AES 快得多……即使对大量数据进行多次散列,我发现性能几乎不可能有任何显着下降。
          【解决方案9】:

          上述算法是加密安全的散列算法(但 MD5 现在不被认为是安全的)。

          但是,有一些算法专门用于从密码中派生密钥。这些是key derivation functions。它们是为与对称密码一起使用而设计的,但它们也适用于存储密码。 PBKDF2 例如使用盐、大量迭代和良好的散列函数。如果你有一个库,是什么实现它(例如 .NET),我认为你应该考虑它。

          【讨论】:

          • 我认为 PBKDF 有很好的用途,但是如果您正在实现一个带密码保护的服务器应用程序,则需要在密码通过网络之前对其进行转换。通常 PBKDF 将用于生成密钥以用于例如对称加密。受密码保护的论坛通常需要使用具有良好抗碰撞性的廉价算法,因为转换的结果本质上是用于检查数据库的“密码”。增加随机性和降低碰撞的可能性是如何提高安全性的方法。随机盐+好的哈希应该可以工作
          • @mpbloch :您无法在密码通过网络之前对其进行转换。您可以使用 SSL 来保护它。由于彩虹表攻击,您需要对密码进行哈希处理。只有在服务器上散列它才有可能。
          【解决方案10】:

          密码学和密码存储的第一条规则是“不要自己发明”,但如果你必须这样做,这里是你必须做的绝对最低限度的安全措施:

          基本规则:

          1. 永远不要存储纯文本密码(这意味着您也永远不能显示或传输它。)
          2. 切勿通过不安全的线路(纯文本、编码或散列)传输存储的密码表示。
          3. 速度是你的敌人。
          4. 随着硬件和密码分析的改进,定期重新分析和改进您的流程
          5. 密码学和过程是解决方案的非常小的部分。
          6. 故障点包括:存储、客户端、传输、处理、用户、法律保证、入侵和管理员。

          步骤:

          1. 强制执行一些合理的最低密码要求。
          2. 经常更改密码。
          3. 使用您可以获得的最强哈希 - 此处建议使用 SHA-256
          4. 将密码与固定盐结合起来(整个数据库都一样)。
          5. 将上一步的结果与存储并附加到此记录的唯一盐(可能是用户名、记录 ID、guid、长随机数等)结合起来。
          6. 多次运行哈希算法 - 比如 1000 多次。理想情况下,每次在前一个哈希中都包含不同的盐。速度是你的敌人,多次迭代会降低速度。每隔一段时间就会将迭代次数加倍(这需要捕获一个新的哈希值 - 下次他们更改密码时再做一次。)

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

          【讨论】:

          • 为什么要使用站点范围的盐以及用户唯一的盐?一个大的随机盐值不够吗?
          • 单盐(任意大小)意味着如果他们生成彩虹表(哈希字典)一次,这对数据库中的每个用户都有好处,因此他们更有可能找到命中更快。如果每个用户都有不同的盐,那么这意味着需要为每个用户生成一个新的查找表。
          • 我理解为什么对所有用户只使用一种盐是不好的。我想知道使用单个站点范围的盐加上用户唯一盐的想法是什么,至少在我看来,仅用户唯一盐似乎就足够了。
          • 如果您使用用户名或其他一些弱盐作为用户特定的盐,则额外的站点范围盐更重要。例如,如果用户在另一个站点上具有相同的用户名和密码,那么您将在两个站点上具有相同的哈希值。除此之外,这只是一个渐进式的改进。
          • 随机盐是最好的。每次用户更改/创建密码时更改它们。您可以将额外的 3-4 个字符存储在与密码哈希相同的字段中,并将它们分开,例如:。所以你的领域从aabbccddeeaabbccddeeaabbccddeeaabbccddeesLt:fb1337ce1afb1337ce1afb1337ce1afb1337ce1a。如果您愿意,可以交换两个子字段的顺序,但关键是,稍后解析的成本很低,并且大大提高了安全性。
          【解决方案11】:

          如前所述,这里不应该使用简单的散列算法是原因:

          http://arstechnica.com/security/2012/08/passwords-under-assault/

          所以使用其他东西,例如http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

          【讨论】:

            猜你喜欢
            • 2012-08-18
            • 2011-08-18
            • 2012-12-19
            • 2011-08-23
            • 2013-10-26
            • 1970-01-01
            • 1970-01-01
            • 2021-06-27
            • 2012-06-10
            相关资源
            最近更新 更多