免责声明:我最初发布了 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 就有足够的时间来实施新的密码政策。
希望答案的技术方面能够深入了解身份验证的工作原理(或应该如何工作)。