如何不向 BE 发送纯文本密码并仍然对其进行验证

How to NOT send a plain-text password to BE and still verify it

我现在有一个困境..

我正在 VueJS 和 NodeJS 上构建应用程序..在身份验证期间,我需要验证密码和用户名是否匹配(显然)。

问题是,我不想将明文密码从 FE (VueJS) 发送到 BE (NodeJS) 但已经用 bcrypt

加密了

问题是,我无法检查给定的哈希值是否与数据库中存储的哈希值匹配。所以这让我只能发送纯文本密码 - 但从我偏执的安全角度来看,这不行......

你们是怎么解决的?

通过 HTTPS 发送“明文”密码是标准做法。密码最终不是纯文本,因为 client-server 通信是根据 TLS 加密的。

在通过 HTTPS 发送密码之前对其进行加密并没有多大作用:如果攻击者获得了加密密码,他们可以简单地使用它,就好像它是实际密码一样,服务器不会知道其中的区别.它提供的唯一优势是保护在多个站点使用相同密码的用户,但这不会使您的站点更安全。

如前所述,通常 HTTPS 的安全层是可信的。

从技术上讲,可以将密码散列一分为二。您可以简单地在客户端(浏览器)上执行一次迭代,其余的在服务器上执行。您希望在服务器上至少执行一次迭代,否则您将获得客户端发送的值以存储在数据库中:即在数据库中获取值的副本会直接泄漏所有登录凭据......不好.

因此,如果您想继续使用该算法,这可能意味着要执行两个单独的 bcrypt 哈希。我想您可以重复使用相同的盐,但最好始终存放单独的盐。当然,在客户端执行 bcrypt 会在本地激增 CPU,这可能会影响性能、加速风扇等,这是假设 JS 会 运行 OK。

最后,如果 TLS 完全被破坏,那么有人可以简单地注入一个脚本来泄露密码。因此,在本地对其进行哈希处理只会以相对较小的幅度提高安全性。它在未来的解密尝试中仍然会有一些用处,但最终你还是不得不依赖 TLS。所以回答“你们如何解决这个问题?”通常是:我们没有。它在移动应用程序或全尺寸应用程序中可能更有意义。

有趣的是,Catena 和 Makwa 等密码哈希竞赛的提交明确允许客户端执行部分哈希。通常,这更多是为了 卸载 密码散列到其他系统并减少对宝贵服务器资源的使用。