我正在组装一个android客户端(可能在未来的iOS, web门户等)和php mysql服务器。服务器端,我目前使用PHPass库对传入密码进行哈希和盐处理。
我应该让客户端通过HTTPS/SSL发送纯文本密码还是客户端应该先做某种形式的哈希。例如,每个客户端都应该简单地sha1(或其他算法)每个传出的密码吗?
大多数网站将通过加密连接SSL/HTTPS以明文形式发送密码。可以在客户端对密码进行散列,但优势很小,而且客户端语言(JavaScrypt)通常很慢,因此您可以在同一时间内计算更少的轮数,这削弱了散列。在任何情况下,为了安全,服务器也必须计算一个哈希值。
优势很小,因为如果攻击者可以进行ManInTheMiddle攻击,他也可以修改/删除执行哈希的脚本(JS)。只有使用SSL/HTTPS的加密连接才能防止MITM攻击,所以无论如何你都需要SSL。
对于应用程序,它看起来略有不同。因为用户首先必须安装您的软件,所以不需要向客户机发送脚本,因此MITM不能修改该脚本。此外,应用程序可以相对快速地计算散列(如果它可以运行本机代码),因此可以在客户端进行足够的轮询。
这就是我要做的:
- 为了方便,通过加密的SSL/HTTPS连接发送明文密码,并计算慢速BCrypt哈希服务器端,就像你现在做的。
- 只有当服务器上的负载变得太重时,才可以将慢速BCrypt哈希的计算移动到客户端应用程序。仍然使用HTTPS发送哈希,然后在服务器上计算额外的快速哈希(例如SHA-256)。这更复杂,因为你必须单独交换和储存盐。
在客户端上散列密码的另一个缺点是,如果不更新客户端,就不能更改散列算法或迭代计数。
对于JavaScript客户端来说,这不是问题,但是你不能轻易保证你的用户将使用最新版本的本地客户端。
所以我会坚持通过HTTPS发送纯密码。
在HTTP的早期,有摘要授权作为基本授权的替代方案。而不是HTTP头文件
Authorization: Basic <credentials>
你会用
Authorization: Digest <credentials>
这是一种算法,通过避免密码以明文形式发送来提高安全性。当时TLS/SSL的出现是以性能为代价的,所以这是一种替代方案。然而,该算法意味着密码必须以明文形式存储在服务器上。因此,您可以选择发送密码明文,但在服务器上有散列,或者以散列形式发送密码,但在服务器上有明文。
不出所料,正如martinstoeckli在他的回答中所说,既然TLS/SSL广泛使用并且易于实现,那么就使用HTTPS来代替。您可以将密码作为散列存储在服务器上,但如果被MITM攻击者截获,则不会暴露明文密码。