使用加盐密码进行身份验证

Authentication with salted password

我正在使用 scrypt 生成用户密码的强哈希值。我想登录用户,但不想通过网络以明文形式发送密码,我该如何检查密码是否正确(没有往返),因为它已被加盐?

我有一个客户端/服务器场景。客户端是桌面计算机上的应用程序(不是网站,也不是http服务器)。

我怎样才能做到这一点?我只走了这么远:我在客户端生成 salt + hash,从中形成一个 mcf 并将其发送到我的服务器。将 mcf 保存到数据库中。我没有发送密码,只是发送了实际上无用的哈希值(因为 scrypt 应该非常强大,并且需要几百万年才能逆转它)。 现在如何让用户登录我的服务,而不将明文密码发送到服务器进行比较?我不能重新散列它,因为它会由于不同的盐而导致不同的散列?我需要将 salt 发送到客户端,对密码进行哈希处理,将哈希发送到服务器,进行比较,然后发回一些身份验证令牌。

我怎样才能做到这一点?身份验证令牌真的安全吗?它可以简单地用来冒充任何人,我猜?

don't want to send the password in plaintext over the wire,

好主意,但如果连接未加密(类似于 SSL/TLS),那么无论您发送什么 都是 明文。如果您在客户端散列密码,并通过网络发送它,那么这就是密码。有人会说这里没有任何好处,但它确实可以防止用户暴露他们可能在其他站点上重复使用的实际密码。 (read more here)

理想情况下,您会使用 SSL/TLS 之类的东西来加密连接。我想如果那不可能的话,在您发送的消息本身上使用带有证书的非对称加密将是重新发明轮子的一种好方法,但我很犹豫是否建议在没有安全人员检查的情况下这样做。很容易搞砸,规则是永远不要推出自己的加密方案。

如果你不能verify/invalidate/update public键,那么这不是一个好的方案。

I would need to send the salt to the client, hash the password, send the hash to the server, compare it, and send some authentication token back

salt 不应该是超级机密,但就这样泄露它并不是很好,尤其是对未经身份验证的用户。如果连接未加密,身份验证令牌、哈希、盐等都可以被拦截。即使他们做不到,您也没有通过这种方法解决用户创建帐户的问题(也许您不需要,但值得一提)。

您必须使用只有服务器才能解密数据的非对称加密。

你的问题没有简短的答案,因为如果你做错了,可能会发生很多陷阱。但正如 Gray 所说,您确实需要 TLS 保护。

如果您想进行客户端 scrypt 处理,我有两个来源可以为您提供有关正确执行此操作的详细说明

  1. Method to Protect Passwords in Databases for Web Applications。如果您不想了解所有基本原理,请跳至第 4 节查看实现(其中 PPF = 您的 scrypt)。
  2. Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server.

它们是略有不同的解决方案,但基于相同的想法,任何一个都应该适合您。