客户端密码哈希与明文对比

3
我正在开发一个安卓客户端(未来可能会有iOS、web门户等),并使用php mysql服务器。目前我在服务器端使用PHPass库对输入密码进行哈希和盐值加密。
客户端是否应该通过HTTPS/SSL发送明文密码,还是应该先对密码进行某种形式的哈希。例如,每个客户端是否都应该对每个输出的密码进行sha1(或其他算法)哈希处理?

请考虑发布在http://security.stackexchange.com上 - Tony Delroy
这个问题已经被讨论过很多次了。请参考在客户端加密密码是否有安全意义、https://dev59.com/KXA65IYBdhLWcg3wogIb和https://dev59.com/6VjUa4cB1Zd3GeqPU9Xj。从安全角度来看,客户端就是客户端,无论是浏览器还是应用程序。应用程序比客户端代码稍微难以破解,但仍然完全不安全。 - Patrick M
是的,您应该在客户端和服务器端都进行哈希处理。尤其是对于您这种移动应用程序,至少在客户端使用恒定盐进行哈希处理是非常必要的。请参考https://medium.com/@harwoeck/password-and-credential-management-in-2018-56f43669d588。 - Leszek Szary
3个回答

3
大多数网站会在加密连接SSL/HTTPS上以明文形式发送密码。客户端进行哈希处理是可以的,但优势很小,而且客户端语言(JavaScript)通常很慢,因此您可以在同一时间计算更少的轮次,这会削弱哈希。无论如何,服务器必须也要计算哈希才能保证安全。
这个优势很小,因为如果攻击者能够进行中间人攻击,他也可以修改/删除执行哈希的脚本(JS)。只有使用SSL/HTTPS的加密连接才能防止中间人攻击,所以您仍然需要SSL。
对于您的应用程序来说,情况略有不同。由于用户首先必须安装您的软件,因此无需将脚本发送给客户端,因此中间人无法修改此脚本。此外,如果应用程序可以运行本机代码,则可以相对快速地计算哈希,因此可以在客户端上执行足够的轮次。
我会这样做:
1.为了方便起见,在加密的SSL/HTTPS连接上以明文形式发送密码,并在服务器端计算缓慢的BCrypt哈希值,就像您现在所做的那样。
2.只有当服务器负载过重时,您才可以将缓慢的BCrypt哈希计算移动到客户端应用程序中。仍然使用HTTPS发送哈希值,然后在服务器上计算另一个快速哈希(例如SHA-256)。这更加复杂,因为您必须单独交换和存储盐。

1
另一个在客户端哈希密码的不利之处是,如果要更改哈希算法或迭代次数,则还必须更新客户端,这样做很困难,不能轻易保证用户使用的是最新版本的本地客户端,对于 JavaScript 客户端来说并不是问题,因此我建议发送经 HTTPS 加密的明文密码。

0
在HTTP的早期,Digest授权是Basic授权的一种替代方案。它不使用HTTP头部,而是使用一个称为“摘要”的字符串来验证用户身份。
Authorization: Basic <credentials>

你会使用

Authorization: Digest <credentials>

这是一种通过避免以明文形式发送密码来增加安全性的算法。那时,TLS/SSL会带来性能成本,因此这是一种替代方案。然而,该算法意味着密码必须以明文形式存储在服务器上。因此,您可以选择发送明文密码但在服务器上具有哈希值,或者将密码作为哈希发送但在服务器上具有明文。

不出所料,正如martinstoeckli在他的答案中所说,现在TLS/SSL已经广泛使用且易于实现,因此改用HTTPS。您可以在服务器上将密码存储为哈希值,但如果被MITM攻击者拦截,则不会暴露明文密码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接