我写了一个小型网络服务器,目前使用基本身份验证而不是 ssl。到目前为止,一切都很好。现在我想(需要)切换到digest auth。但是我不知道如何使用未在数据库中以明文形式存储的密码来完成这项工作?我只存储了用户密码的密码摘要(使用 bcrypt 生成)。http摘要身份验证是否可能?
2 回答
刚才正在研究这个。首先,我通读了RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication,以深入了解该规范,并了解它如何适用于 REST API 身份验证。
遇到了和你一样的问题——<em>摘要式身份验证是否意味着服务器需要以明文形式存储用户密码?
这个Stack Overflow 答案清楚地表明:不。服务器不存储明文密码—<a href="https://www.rfc-editor.org/rfc/rfc2617#section-4.13" rel="nofollow noreferrer ">它应该存储(username|realm|password)
.
除了一件事——规范规范只支持使用 MD5 作为散列函数之外,那本来很好。
当然,您可以同时存储bcrypt 散列和MD5 散列,但这样做只会破坏 bcrypt 散列的安全性,从而有效地使其无用(因为攻击者可以将他的努力转向暴力破解 MD5 散列)。
所以,我退后一步想,为什么不忽略规范,两边都使用 bcrypt作为哈希函数(bcrypt(username|realm|password)
)?
好吧,除了故意变慢之外,bcrypt 还具有最大密码长度,这使得它不适合用作通用摘要算法。
唷,现在我的头在游泳,但我仍然想再试一次。一些建议是使用带有 SRP 的 TLS 或经过身份验证的加密,特别是 EAX,但我觉得对于一个简单的 Web 服务来说,这些建议可能太过分了。
简而言之,如果您真的一心想要这样做,您可以通过使用初步 hash 来解决 bcrypt 的字符限制。
长话短说,您似乎可以这样做:
bcrypt(sha256(username|realm|password))
并用它代替H(A1)
规范的混蛋版本。
现在的问题变成了——所有增加的复杂性真的值得吗?我们是否通过 HTTPS 的基本身份验证获得了任何额外的安全层?
现在的问题变成了——所有增加的复杂性真的值得吗?我们是否通过 HTTPS 的基本身份验证获得了任何额外的安全层?
我可以看到一个,当您使用基本身份验证时,您的 HTTP 客户端将授权标头作为base64(password)
因此,如果您打开 Web 浏览器,并且有人打开浏览器 Web 控制台,他可以对您的密码进行 base64 解码。
而对于摘要身份验证,授权标头是 md5 哈希(并且包含随机数哈希以防止重放攻击)