如果密码是用 "salt" 加密的,如何在数据库中检查密码?

How to check password in database if password was encrypted with "salt"?

我读过 "salting a password" 改进密码保护的方法。但是如果密码以复杂的形式存储,我不明白如何检查密码。我假设用户的密码在客户端被加密,然后它的哈希码与数据库中的哈希码进行比较。我没有网络开发经验。我只是在学习网络安全的方法。

加盐使攻击者更难重新创建原始密码。所以是的,它是一种改进密码保护的形式。但是你需要从不同的角度来看待它。

关于您的问题:

I don't understand how to check the password if it is stored in a complicated form.

你不知道。当您的用户创建密码时,您计算哈希值并仅存储哈希值。当他们重新登录时,您再次计算哈希值,如果匹配,您就知道用户提供了相同的密码。

I assume that the user's password is encrypted on the client then its hash code compares with hash code in the database.

有些方法用户甚至不向服务器发送密码,但对于传统的用户名+密码登录,用户以明文形式发送密码(希望通过 https),服务器计算哈希值服务器端。

更详细一点

你不想盯着明文密码,因为密码是只有用户知道的秘密。

一般来说,散列是一种更好的密码存储方式。这是 eleganz,因为您只保存校验和,当用户登录时,您再次计算哈希值并检查它们是否匹配。这样更好,因为您不存储密码,因此不会丢失它。

但是:如果两个用户有相同的密码,他们也有相同的散列值。这很糟糕,因为现在您对密码的了解比您应该知道的要多,而且对于攻击者来说这很有趣,因为破解此密码将使他们能够访问多个帐户。

更糟糕的是,有常用词的预计算列表(因此称为 rainbow tables)。 5f4dcc3b5aa765d61d8327deb882cf99 例如是 password 的 MD5 散列。有像 crackstation 这样的网站,您可以在其中反向查找哈希。

结合这两个弱点,您就会明白为什么简单的散列不足以充分保护密码。

这就是加盐的地方。如果服务器向每个密码添加一些额外的、唯一的数据位,那么使用相同密码的两个用户现在会得到不同的哈希值。

| Salt  | Password | MD5                              |
|-------|----------|----------------------------------|
| salt1 | password | 421ec89b160730497225a2bfac63305c |
| salt2 | password | 6b60d583eb2b0888b91c8fe72d652ed1 |

此外,这使得彩虹 table 更难预先计算常用词,因为它还需要预先计算所有可能的盐。

服务器当然必须记住它使用的盐,否则当用户登录时它无法再次计算相同的散列。

如果攻击者获取了您的数据库,他们将拥有哈希和盐。虽然他们不能再使用 rainbow table,但他们仍然可以通过猜测密码来发起攻击。这仍然要困难得多,因为他们需要用自己的盐来猜测每个用户的每个密码。

您可以通过使用故意低效的哈希来使其变得更加困难,例如。 PBKDF2、Argon2、BCrypt *。如果知道密码的用户登录系统,慢速密码功能几乎没有效果。再多几毫秒在这里并不重要。但是,如果需要计算数百万组合的攻击者现在还必须使用比通用哈希慢 100 倍的哈希函数,则他们需要多 100 个资源来攻击哈希。希望这能使攻击对他们没有吸引力。

*) 在撰写本文时。

既然你说你目前正在学习,我会尝试做一些介绍。并且会尽量缩短。

  • Salt 是我们生成并添加到纯密码/密码短语中的随机字符串。它可以在 Hash Value.
  • 旁边的数据库中存储为 plain
  • Hashing 是一种将数据映射到具有固定长度的值的方法。此值称为 Hash Valuechecksum。散列是单向的。 MD5 和 SHA256 是散列算法的一些示例。

盐的好处

我们在这里所做的基本上是确保所有用户都有唯一的密码(在哈希输出中)。这将避免可能的攻击者捕获用户数据同时计算多个用户的密码。

换句话说,当有人查看所有用户名和密码时,他们将无法说出哪些用户使用相同的密码。

下面的table可以帮助我们更好地理解它。

| username | salt             | plain-password |salted-password-to-be-hashed | hashed-password                                                  |
|----------|------------------|----------------|------------------------------|------------------------------------------------------------------|
| user1    | db97913154884d72 | password1      | password1db97913154884d72     | 5027a576d161385ddcc72e47280f85729fc3ba5e48e0a018e2f68dc7d13e93cc |
| user2    | 8fc2884d127fd40b | password1      | password18fc2884d127fd40b    | 6069e0e5a06d41ed0ffb06d0c0e26dd7dea3cb14de80e4075848d3217b40b783 |

以下步骤演示了存储和验证的基本方法

如何存储? (注册)

  • plain-password 从客户端通过 https 到达您的后端应用程序。
  • 后端应用程序生成 salt 并将其附加(或添加)到普通密码。
  • 然后,使用哈希算法(例如 SHA-256、MD5 等)计算 hashed-password
  • 最后,将usernamesalthashed-password存入数据库。 (从不存储 plain-password 和/或 salted-password-to-be-hashed。)

如何认证?

  • plain-password 从客户端通过 https 到达您的后端应用程序。
  • 后端应用程序从数据库中获取用户特定 salt 并将其附加(或添加)到纯密码。
  • 然后,使用相同的哈希算法计算 hashed-password,并将其与存储的进行比较。

更高级一点:

您还可以添加第二种名为 pepper 的盐。这是要添加到纯密码的另一个随机字符串(胡椒 + 纯密码 + 盐)。但是在这里,pepper 存储在另一个数据源中,而不是 salthashed-password.

旁边