bcrypt 散列与比较用户登录

问题描述

首先,我为这个问题道歉。我知道有很多类似的明显问题要求如何在 X 应用程序中实现 bcrypt,但在这里我问的是两种策略。

我最近在用户登录中实现了 bcrypt。基本上:

  • 用户将凭据发送到我的 rest api 服务器
  • bcrypt.hash 给定的密码,并使用简单的 where 子句将其与数据库进行比较,如下所示:

WHERE mail = $mail and password = $my_just_hashed_password

  • 如果我在数据库中找到一个用户,我认为给定的密码是正确的。否则,我拒绝该请求。

这与首先从给定的唯一邮件中选择用户,然后bcrypt.compare 给定的密码和数据库中的散列密码几乎相同。

我的问题是,哪个更好?我知道 bcrypt 散列函数旨在用于安全地存储敏感数据,但为什么不使用它来验证用户

解决方法

当您使用 bcrypt 正确散列密码时,您将至少 16 个随机字符的字符串附加到密码中,并通过 bcrypt 运行整个过程数千次。完成哈希算法至少需要四分之一秒。然后你存储随机数。字符串,称为盐,以及散列密码。

要验证密码,您需要从存储的密码哈希中提取盐,然后将要验证的密码与盐一起散列。两个哈希值必须匹配。

由于盐的原因,您永远无法将一个哈希与另一个进行比较并期望它们相等。

请阅读此内容。 https://en.m.wikipedia.org/wiki/Bcrypt#Description

为什么这么复杂?因为网络蠕变。因为网络蠕虫有时可以窃取大型网络应用程序的 users 表。他们窃取用户名和电子邮件已经够糟糕的了,但我们不希望他们也窃取密码。见 Adob​​e。见阿什利·麦迪逊。

如果没有随机盐,攻击者就有可能构建查找表来帮助从哈希中猜测密码:现在 RAM 很便宜。随机盐意味着查找表不再可行。您知道有些用户会选择 654321 作为密码,我们不希望攻击者能够在所有密码中搜索该密码和其他 common 密码的散列版本。

此外,我们使用 Blowfish 密码算法,因为它比 MD-5 和各种 SHA 哈希值慢。这很好:我们希望攻击者面对缓慢的散列算法,因此他们无法每秒猜出数千个密码。使用 bcrypt 进行强力密码猜测非常耗时。

最后,使用经过仔细验证的加密算法是信息安全的原则。自己动手是不明智的。假设网络小偷比你更聪明、更有动力,你就会更安全。

请不要使用您描述的方法。

,

我将提供已批准答案的替代答案,重点是安全性...

由于电子邮件是唯一的,我会首先仅根据电子邮件找到用户,从检索到的用户那里获取密码,然后使用 bcrypt 进行比较。如果电子邮件存在,但密码不匹配,则可能存在暴力攻击,您可能需要记录这些失败的尝试,以便您可以锁定帐户或添加验证码以减缓/防止攻击。

这有什么不同

原始解决方案

  1. 从电子邮件和散列密码中获取用户
  2. 如果凭据正确,很好,用户可以登录。这里没有问题
  3. 如果未找到用户,电子邮件或密码是否不正确?仅凭这个查询是无法知道的。
  4. 潜在攻击者可以通过对输入的电子邮件尝试不同的密码来继续尝试访问潜在帐户。

替代解决方案

  1. 仅从电子邮件中获取用户
  2. 如果用户存在,将数据库中的哈希用户密码与输入凭据的哈希密码进行比较(使用 bcrypt compare)。
  3. 如果密码不正确,请将其记录到另一个表 (USER_FAILED_LOGINS) 中,在 3 次尝试失败后,添加一些安全措施,例如验证码。
  4. 如果密码正确,很好,请登录用户。

您当然可以使用原始解决方案,如果凭据不正确,则只需执行另一个查询即可确定电子邮件是否存在并在此时实施安全措施。只是要警惕这些类型的攻击并防止它们。另外,请确保您在 SQL 中使用了准备好的语句。