加盐、散列密码存储如何与基于明文、随机数和散列的身份验证相结合?

信息安全 密码 验证 贮存 随机数
2021-08-13 23:50:10

我的理解如下:

  1. 为了安全地存储密码(例如在数据库中),您使用为此目的而设计的散列算法(设计速度较慢,例如 bcrypt),并且您为每个密码使用唯一的盐。这使得有权访问数据库的攻击者恢复密码变得困难/缓慢,因为他们不能使用彩虹表,并且每次暴力尝试都比简单的 md5 或 sha1 花费更多时间。

  2. 为了通过纯文本协议(即非 SSL)安全地验证密码,服务器向客户端发送一个随机数,客户端将密码和随机数(可能还有时间戳)结合起来,在它们上运行散列算法,然后将该哈希传输到服务器,服务器运行相同的算法并进行比较。这避免了以纯文本形式发送密码,并且也使得重放攻击不可能,只要服务器不能被欺骗两次接受相同的随机数。

问题是,对于身份验证部分,服务器需要知道实际的明文密码。所以你不能像#1那样安全地存储它们。

现在,服务器可以将盐传输给客户端,客户端可以先计算加盐、散列的密码,然后执行#2。但是,加盐哈希密码实际上变成了明文密码,所以你仍然没有真正的#1。

所以我的问题是,有没有办法同时做#1和#2?

3个回答

看看安全远程密码协议(维基百科斯坦福)。它在客户端使用密码的散列(选择您最喜欢的慢速加盐散列),但服务器仅通过离散求幂该散列中获得“验证器” 。实际身份验证通过使用两个随机数(一个客户端生成,一个服务器生成)、哈希(仅客户端)和验证者(服务器端)的非对称密钥交换进行。生成的密钥旨在用于加密会话的其余部分,但可以简单地对其进行验证和丢弃。

好处:

  • 密钥交换本身实际上是一种零知识证明,这意味着侦听器、中间人或服务器冒名顶替者无法获得有关密码的信息。如果这些是唯一可能的攻击类型,那么单字母密码就足以保证安全。
  • 在线字典攻击(客户端冒名顶替者)每次尝试只能测试一个密码(协议的早期版本允许两个)。
  • 如果攻击者复制服务器的验证者数据库,他们只能通过慢散列求幂运行每个候选密码来运行离线字典攻击。他们不能使用验证者来冒充客户。
  • 只要服务器的验证者保持秘密,交换交易就有效地向客户端验证服务器(以及客户端对服务器)。

是的,这是可能的。这里描述了两种算法,它们都避免了在服务器上存储明文等效项的需要(同时无需通过线路发送明文密码即可进行身份验证)。

如果我错了,请纠正我,但是,您可以将散列密码保留在服务器上。所以它安全地存储。并使用随机数作为盐进行身份验证。我看到的一件大事是服务器不需要以这种方式知道明文密码。它仍然可以证明该人最终输入了正确的密码,但是通过比较哈希而不是明文。在我的场景中,这个密码是纯文本的唯一地方是网络浏览器窗口,在它被散列之前(两次,一次是普通的,一次是用已知的盐),然后通过网络而不是纯文本发送

考虑下面的场景

  1. 客户端尝试连接
  2. 服务器生成随机数
  3. 服务器向客户端发送随机数。用随机数作为盐再次散列哈希。将密码的哈希值作为输入,将随机数作为盐的哈希值。
  4. 客户端通过相同的散列算法对 pwd 进行散列,生成存储在服务器上的相同散列。
  5. 客户端然后以与服务器相同的方式进行自己的单独哈希(密码哈希的哈希,随机数作为盐)
  6. 客户端将 nonced 哈希传输到服务器。
  7. 服务器在该一次身份验证时接受它是正确的,并且永远不会再次接受相同的 nonced 哈希