盐值密码哈希

4
我正在尝试为Web应用程序创建登录系统,但有几个问题困扰着我。我使用128位随机盐和sha2-512哈希将密码存储在我的数据库中。
然而,我目前在使用HTML表单时以明文形式发布密码到我的应用程序中,无论是在创建账户还是用户登录时都是如此。我知道这是错误的。
我需要在客户端中对密码进行哈希处理吗?如果需要,那么我该如何考虑当前在数据库中生成和存储的盐?
注意:我这样做是为了学习,而不是在生产系统中使用。
4个回答

3
最好的做法通常就是使用SSL加密。如果你确实需要在客户端进行哈希,这就是我会采取的方法:
  1. 当您首次存储密码时,请使用保存的盐值对密码进行哈希,这是一种常见的方法。
  2. 当有人需要登录时,请向他们发送保存的盐和第二个随机生成的盐。
  3. 客户端将使用保存的盐对明文密码进行哈希,然后使用随机盐并将哈希发送到服务器。
  4. 服务器将使用请求中使用的随机数对存储的密码进行哈希并进行比较。
这样做是安全的,因为它确保传输的哈希是与请求唯一相关的(它使用单个请求的随机盐),因此未来不能通过再次发送哈希来伪造登录。向客户端发送其保存的盐并不危险,因为假定密码破解器将访问已保存的盐(如果他们获得对数据库的访问权)。两个哈希是必需的,以防止您必须存储明文密码。

如果实现正确,这并不是一种不安全的解决方案-至少暴露盐和算法的轻微安全折衷可以被视为可接受的。但是,它相当复杂,需要某种会话状态处理。 它不能很好地转换为无状态服务,其中凭据通常在每个请求中传输。可以使用类似安全登录令牌的东西来解决这个问题,但这会引入复杂性(因此,安全风险)。最佳方法是在服务器上进行哈希并通过加密连接传输凭据。 - chris

2
您应该使用 SSL 来加密传输密码,以防止中间人拦截数据包并读取发送的任何凭据。即使您在客户端中预先哈希密码,中间人仍然可以使用该值来伪造身份。
但是,真正让我担心的是使用 SHA-512。很多人使用密码哈希进行密码存储,但普遍意见忽略了一个非常重要的问题:这些哈希算法被设计成“快速”的。也就是说,成为 SHA(或类似)哈希的要求之一是能够在嵌入式硬件上快速哈希大型文档。
这与密码存储的要求完全相反,因为它允许高性能 GPU 上的专用程序以惊人和可怕的速度暴力破解密码!
这就是为什么一些专门用于密码存储的哈希算法被开发出来。我一直在使用的是 Bcrypt,它足够缓慢以防止暴力破解攻击,可以调整以抵消未来更快的硬件,并且还有额外的好处,可以为您处理盐。

1

在客户端对密码进行哈希处理需要在客户端使用盐。这也会暴露您的算法,使得客户端易于被黑客攻击。最好的做法是通过 SSL(HTTPS)执行此操作,以便整个事务都加密,并且身份验证仅在服务器上发生。

即:您的用户 ID 和密码以加密方式从客户端传输。Web 服务器解密数据并将其传递到您的服务器端身份验证函数,其中您查找用户和相关盐,执行密码+盐+哈希并将其与存储的哈希进行比较。这意味着哈希和盐根本不需要从服务器传输。


0
你需要在任何传输密码的页面上使用SSL。如果你试图在客户端加密它们,那么这将是通过JavaScript实现的,而且非常容易被反向工程化。

1
哈希的目的在于它是不可逆的。 - Zack Bloom
1
@ZackBloom,您仍然可以实现双向加密,仅用于在客户端和服务器之间传输密码(在服务器上将其进行哈希处理并存储)。 - Matthew
然而,有人可以轻易地禁用 Javascript,从而禁用客户端哈希。这意味着密码将以明文发送。 - moshjeier
@MatthewPK 正如我所说,这是不必要的,因为哈希已经不可逆转了。 - Zack Bloom
@MatthewPK 哈希的目的是使其在密码学上无法被反向破解,因此使用哈希算法时,您无法重构明文。了解哈希如何计算并不是问题。在客户端进行哈希与在服务器上进行哈希一样安全。在客户端进行哈希的危险在于,拦截传输的人可能会获取哈希并将其用于验证自己的请求,就像您传输明文密码一样。但是,您可以使用双重哈希,请参阅我的答案以获取更多详细信息。 - Zack Bloom
显示剩余3条评论

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