【问题标题】:How do modern websites check your password without actually storing it?现代网站如何在不实际存储密码的情况下检查您的密码?
【发布时间】:2012-11-20 14:55:28
【问题描述】:

有人告诉我,您不应该将用户密码存储在数据库中,但是如果我无法保存用户密码,我该如何验证用户身份?仅仅对它们进行加密就足以保证它们的安全吗?

最近新闻中有几篇报道称,LinkedIn 等知名网站遭到入侵,我认为如此知名的网站不会存储纯文本密码,因此假设它们已加密。

【问题讨论】:

标签: security hash passwords hashtable


【解决方案1】:

免责声明:我最初发布了 this on Quora,但觉得答案更适合 Stack Overflow。

用于存储和检查用户密码而不实际保留密码的方法是将用户输入与存储的哈希值进行比较。

什么是散列?

散列是通过一种算法传递可变长度的数据(小密码、大密码、二进制文件等)的过程,该算法将其作为一组称为散列值的固定长度返回。哈希仅以一种方式起作用。一个由几 Mb 组成的 *.img 文件可以像密码一样进行哈希处理。 (实际上,在大文件上使用散列来检查它们的完整性是一种常见的做法;假设您使用 bittorrent 下载了一个文件,当它完成时,软件会对其进行散列并将您拥有的散列与您应该使用的散列进行比较有,如果他们匹配下载没有损坏)。

使用哈希的身份验证如何工作?

当用户注册时,他会给出一个密码,比如pass123,然后将其散列(通过任何可用的散列算法:sha1、sha256 等,在这种情况下为 md5)到值32250170a0dca92d53ec9624f336ca24,该值是存储在数据库中。每次您尝试登录时,系统都会实时对您的密码进行哈希处理,并将其与存储的哈希值进行比较,如果匹配,您就可以开始了。您可以在这里尝试在线 md5 哈希:http://md5-hash-online.waraxe.us/

如果两个哈希值相同怎么办?用户可以使用不同的密码登录吗?

他可以!那就是所谓的碰撞。假设在一个虚构的散列算法中,值pass123 会产生散列ec9624,而值pass321 会产生完全相同的散列,那么散列算法就会被破坏。由于发现了冲突,常见的算法 md5 和 sha1(LinkedIn 使用的那个)都被破坏了。被打破并不一定意味着它不安全。

如何利用碰撞?

如果您可以生成哈希,则与您可以将该站点识别为用户的用户密码生成的哈希相同。

彩虹桌攻击。

破解者很快就明白,一旦他们捕获了一个哈希密码表,就不可能逐个利用密码,因此他们设计了一种新的攻击向量。他们将生成存在的每一个密码(aaa、aab、aac、aad 等)并将所有哈希值存储在数据库中。然后他们只需要使用所有顺序生成的哈希(亚秒级查询)在数据库中搜索被盗的哈希并获得相应的密码。

救命稻草(LinkedIn 大失败的地方!)

安全性由破解者破解您的密码所需的时间以及您更改密码的频率来定义。彩虹桌的安全性下降得非常快,所以业界想出了盐。如果每个密码都有一个独特的转折点怎么办?那是盐!对于每个注册的用户,您都会生成一个随机字符串,比如 3 个字符(业界建议使用 16 个字符 - https://stackoverflow.com/a/18419...)。然后将用户密码与随机字符串连接起来。

password - salt - sha1 hash  
qwerty   - 123  - 5cec175b165e3d5e62c9e13ce848ef6feac81bff  
qwerty   - 321  - b8b92ab870c50ce5fc59571dc0c77f9a4a90323c  
qazwsx   - abc  - c6aec64efe2a25c6bc35aeea2aafb2e86ac96a0c  
qazwsx   - cba  - 31e42c24f71dc5a453b2635e6ec57eadf03090fd  

您可以看到完全相同的密码,给定不同的盐值,生成完全不同的哈希值。这就是 salt 的目的,也是 LinkedIn 失败的原因。请注意,在表上您只会存储哈希和盐!永远不要密码!

拿到 LinkedIn 哈希值的人做的第一件事就是对哈希值进行排序,看看是否有匹配项(因为多个用户有相同的密码——真可惜!)这些用户是第一个下降。如果通行证表被加盐......这一切都不会发生,他们将需要大量的时间(和计算机资源)来破解每一个密码。这样一来,LinkedIn 就有足够的时间来实施新的密码政策。

希望答案的技术方面能够深入了解身份验证的工作原理(或应该如何工作)。

【讨论】:

  • 散列算法存在冲突这一事实并不会使其“崩溃”。如果您不将密码的大小限制为足够低的限制,那么可能的密码将比散列多(任何散列算法几乎总是如此)。好的散列算法只是尽可能地减少冲突,并尝试“相似”的输入值不会导致相同的散列。此外,散列的大小与冲突的概率成反比(使用非糟糕的算法)。可能的哈希值越多越好。
  • -1 此答案包含几个过时的概念,不应用作密码安全性的参考。这可能部分是因为它试图回答一个过于宽泛的问题,并且需要更长的答案才能完成。
  • 写得不好,没有提到强化等基本概念,而且关于碰撞的部分具有高度误导性。冲突将允许您创建一个您知道两个不同有效密码的用户。不是一个非常有用的攻击。找到与其他用户的哈希值匹配的密码,称为前映像,即使使用 MD5,这仍然非常昂贵。
  • @CodesInChaos 所说的“极其昂贵”的意思是 2^123.4 量级的攻击,这需要超过宇宙年龄才能完成。请注意,目前对 MD5 可行的攻击是选择前缀攻击,在攻击散列密码时基本上没有用。这并不是说 MD5 是用于密码保护的好算法(也不是任何通用散列函数,如 SHA-* 系列)。没有提到像 bcrypt 这样的专用密码哈希函数(以及为什么应该使用它们)是我在这个答案中遇到的最大问题。
  • @NullUserException,我相信你,但至少在阅读了这个问题之后,我对盐有所了解。也许这里应该有一个“进一步阅读”页脚?
【解决方案2】:

真的很喜欢,当有人问这个问题时,因为有人想要做得更好。只知道几个重点,即使是知名网站也可以避免很多麻烦。

最近我写了一篇关于Hashing passwords 的教程,它使用了一种希望简单易懂的语言。它允许使用 SQL 注入,解释盐和胡椒的用法,并指出需要慢速密钥派生函数。

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2016-11-04
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    • 2016-05-17
    • 2011-06-13
    相关资源
    最近更新 更多