公开 bcrypt 密码哈希是否安全?

信息安全 密码 Web应用程序 密码管理 javascript
2021-08-30 14:17:14

我正在构建一个需要支持用户离线切换的 Web 应用程序,并且想知道公开 bcrypt 哈希以验证用户是否安全。

基本流程:

  1. 主要用户在 Web 应用程序在线时登录,访问服务器
  2. 服务器返回同一公司内其他用户的列表,包括他们的 bcrypt 哈希(哈希成本为 10)
  3. 与之前使用 JS bcrypt 库返回的相比,允许其他用户在 Web 应用程序离线时通过输入自己的密码来创建记录

该应用程序本身的风险相当低,并且在很多情况下用户都会有动机冒充同事,但我希望能做到这一点。

提前感谢您的任何见解。

(一个后续问题是:与服务器同步时,如何向服务器证明其他用户在创建记录之前确实进行了离线身份验证,但作为自己的帖子可能会更好。)

2个回答

不,这不好,但这不是 bcrypt 哈希的问题,而是因为您将身份验证从您信任的服务器(因为它是您的服务器)移动到用户的设备(您不能信任)。现在需要一个简单的调试器来更改“此密码有效吗?”的结果。检查从“否”到“是”。

此外,它还为攻击者提供了对哈希列表的持久访问权限。因此,攻击者可以在他们想要使用的任何计算机上暴力破解该列表。

简而言之,这是一个非常糟糕的主意。

正确的做法是缓存声称是您的经过身份验证的用户的同事的用户的操作,并让该同事在他们重新在线后立即向您的服务器进行正确的身份验证,以实际提交他们对服务器所做的任何事情. 一种方法是简单地存储用户输入的密码,然后以您在“正常”登录期间使用的任何形式将其发送到服务器。如果可行,那么用户已经验证了自己,并且存储的可以进行动作。如果没有,那么告诉用户他输入了错误的密码,除非他输入正确的密码,否则他的操作无法执行。

通过将密码哈希推送到客户端,您会将它们暴露于离线暴力攻击。如果密码足够强,那是完全可以接受的。但这是一个危险的假设。

您可以要求每个用户确认他们希望发布自己的哈希(在向他们解释风险之后)。但是有很多用户会高兴地说他们了解风险并选择了足够强的密码,即使他们实际选择的是password12345!!!

此时,您必须评估此功能与允许用户在脚上开枪的风险相比的重要性。

然而,您的设计中还有另一个缺点,那就是验证离线更新。依靠客户端来验证用户是不够的。

将用户密码与更新一起存储并在联机后将两者发送到服务器将解决仅执行客户端验证的问题。但是你会引入三个新问题:

  1. 输入更新时,它不会捕获输入错误的凭据。稍后,当服务器验证这些凭据时,最初键入它们的用户可能无法解决该问题。
  2. 更新将具有延展性。修改存储在客户端设备上的更新以使其在到达服务器后执行不同的更新将是微不足道的。
  3. 您将在设备上以明文形式存储密码,这是安全方面的一大禁忌。

我没有看到任何方法可以防止密码的离线暴力破解,同时仍然允许在输入更新时验证密码,并且出于可用性原因,验证是必要的。

因此,我将采取的方法是根据用户密码和盐创建一个公钥对,并使用相应的私钥对更新进行签名。这意味着更新不再具有延展性,并且不需要存储和传输密码,而您只需存储和传输签名。

当然,客户端仍然需要知道盐和用户名才能生成正确签名的交易。它首先需要知道公钥或哈希来验证它,这允许离线暴力攻击。

您可以将经过哈希验证的客户端截断为仅一个字节,这使得离线暴力攻击不太可行,并且仍然有 99% 的机会在客户端检测到不正确的密码。

在服务器端,您仍应使用加盐散列验证传输的公钥,以确保您只收到有效交易。

显然,您正在设计的应用程序的任何设计都会留下很多错误空间,因此必须由多名安全专业人员审查最终设计和代码,以确保最终结果是安全的。