我为什么要散列密码?

信息安全 密码 哈希
2021-09-06 06:31:48

我读过每个好的网络应用程序都应该散列密码。我发现了很多关于散列的文章。所以我开始在我的网站上实现散列,然后我问自己为什么要这样做?当用户将他或她的登录名(名称+密码)发送到服务器时,服务器从数据库中加载给定用户名的密码,然后比较密码。用户无法从数据库中获取密码。

很可能我误解了这个概念,所以谁能告诉我为什么有人应该使用散列?

4个回答

出于任何原因,您的数据库可能会受到损害,并且其数据可能会被其他人获取。如果密码是我们所说的纯文本您将泄露用户信任您的一条敏感信息:他们的密码(很可能是在多个服务中共享的密码)。这是一个非常严重的问题。

密码通常不是纯文本,而是使用单向散列函数进行散列如果用于散列的加密函数很强大,那么密码会更安全,因为即使有人掌握了您的数据库,计算密码也是不可行的(仅给定散列)。

另一方面,散列信息对您仍然有用:因为相同的散列函数将始终为相同的输入产生相同的散列,您仍然可以散列任何尝试的密码并将结果与​​您保存的散列进行比较以验证用户的身份验证尝试(事先不知道正确的密码)。

当然,现在仅仅散列是不够的。查找攻击通常使解密(从可预测的密码创建的哈希)非常可行。为了应对这些攻击,每个密码都与一个唯一的随机生成的输入(称为salt一起进行哈希处理salt 以纯文本形式存储在数据库中,不必保密,因为它的主要目的是使预先计算的哈希字典变得无用。

几乎所有严肃的平台都使用散列和加盐来存储用户的密码(除非他们使用不同但我不知道的相对安全的东西)。顺便说一句,这正是您可以在各种服务中重置密码但几乎无法恢复的原因:哈希可以被系统覆盖,但无法解密。

为了用户的安全和对密码进行加盐和哈希处理,您应该尽一切努力做理智的事情。网上有很多资源可以详细解释这个过程和陷阱。其中之一是“安全加盐密码散列:如何正确执行”

您的数据库可能由于多种原因而受到损害,它一直在观看新闻(甚至是网络上一些最大的网站)。如果您的数据库因任何原因受到损害,则对您的用户散列他们的个人信息只是一种安全预防措施。

散列密码的最基本原因是,如果存储的密码版本被盗,则无法公开读取。

请注意,我说的是存储版本- 如果密码从未以任何形式存储(这不太可能),那么对它进行散列是没有意义的。但是你不可能(也不切实际)永远不会存储它,所以它应该被散列。您可能认为您的数据库是安全的,但有一些非常聪明的人比您聪明得多。

但是你也应该注意,单独散列它在很大程度上是无效的——你还应该在散列之前给它加盐这意味着您在散列之前向密码(密码中的任何位置)添加一个已知(最好不太可预测)的值 - 这有助于通过使用彩虹表来减慢密码的破解速度

密码的传输应该通过由 TLS 保护的连接 - 即它应该通过 HTTPS。这样,您可以以明文形式发送输入的密码(您不应尝试在网页上对其进行加密或散列),然后服务器端代码对接收到的密码进行加盐和散列,然后再将生成的散列与存储在数据库。

散列密码可防止您的密码在数据库遭到破坏时遭到破坏。它通过两种方式做到这一点,1. 它通过使计算上不可能从哈希中获取密码来隐藏用户密码,以及 2. 它可以减慢彩虹表的生成以查找已知密码。

散列函数是单向函数,这意味着如果您知道原始数据,您可以生成散列,但拥有散列不会给您原始字符串(无论如何理论上)。想到这个最简单的方法是想到编程中的 mod 函数 (%),如果我要问你什么值给你 n % 6 = 5 有很多答案,5%6 = 5, 11%6 = 5, 16%6 = 5 以此类推...但是您无法仅通过知道 n%6 = 5 来确定我使用的是哪个 n。加密哈希函数提供了这种数据隐藏,除了它非常很难找到冲突(产生相同哈希的两个值)。例如,SHA2 提供 128 位的熵,这意味着它需要 2^128 次尝试才能找到冲突(尽管 SHA2 是 256 位算法,但它就像所有散列函数一样容易受到生日悖论的影响)。

因为加密哈希函数具有这种数据隐藏的特性,所以当有人查看您数据库中的密码时,他们通常无法仅通过查看这些密码来判断这些密码是什么

彩虹桌

彩虹表是预先散列的密码表。因为大多数人使用易于记忆的低熵密码,所以坏人可能只拥有一张已知密码表,并根据表中的内容检查您的散列值。为了减轻这种情况,您使用盐,它只是您连接到密码的随机字符串。 建议为每个用户密码使用不同的随机盐盐应该通过传递一个随机值来生成(对于 C#,您可以使用RNGCryptoServiceProvider) 在任何时候创建或更改密码时将其转换为伪随机数生成器(例如哈希函数)。许多程序员认为 salt 必须是一串字符,但事实并非如此,您可以在数据库中使用 Base64 编码的字节,然后在进行检查之前对其进行解码。这将改变原始字符串,使其足以使哈希与彩虹表中的内容不匹配,并使其无法进行简单的查找。良好的密码散列函数具有称为“雪崩效应”的属性,这基本上意味着 1 位更改会导致至少 50% 的位发生更改。因此,使用 salt 进行散列可以通过简单的查找更难弄清楚这些密码是什么,从而提高了您的整体安全性。

快速计算

如今,计算机速度非常快,使得动态计算彩虹表成为可能。因为盐通常以明文形式存储在与哈希密码相同的表的另一列中,所以有权访问您数据库的坏人可以使用已知字典和您在数据库中的盐即时计算彩虹表。

对于这种情况,我们想要一种方法让他们更难做到这一点。虽然我们中的许多程序员都在努力使我们的应用程序更快,但实际上我们希望事情进展得慢一点。诸如 SHA 系列之类的散列函数可以非常快速地散列大量数据,因此它们不适用于密码散列。BCrypt等哈希函数引入了工作因子,较高的工作因子会导致算法执行速度较慢,因此很难生成彩虹表。随着计算机变得越来越快,您只需增加您的工作因子并重新散列您拥有的哈希值。BCrypt 的一个很好的副作用是它会为你生成盐,所以你不必弄乱 RNGCryptoServiceProvider 等,如果你使用BCrypt.NET您不需要额外的列来存储盐,因为它是您返回的结果字符串的一部分。这个想法是调整工作因素,以便用户在登录时不会注意到延迟,但是当坏人试图暴力破解密码或试图动态生成彩虹表时,他们的速度真的很慢.