公开暴露盐是否可以接受?

时间:2015-02-23 17:57:18

标签: security hash cryptography passwords salt

我正在为移动应用构建REST API。我需要处理身份验证。据我所知,这些是关于密码存储的最佳实践。

在客户端注册

  1. 让用户选择密码
  2. 从强随机数生成器
  3. 创建足够长的随机盐
  4. 将salt附加到密码并哈希。
  5. 将哈希和salt发送到服务器并将其存储在数据库中
  6. 服务器端登录

    1. 公开一种方法,为给定的用户ID(电子邮件)返回用户的盐
    2. 客户端登录

      1. 用户输入用户名和密码
      2. 检索给定用户标识的盐
      3. 将salt附加到密码并哈希。
      4. 将哈希发送到服务器,检查它是否相同并验证用户
      5. 显然,这种方法的周点是攻击者可以毫不费力地为任何用户查看盐。这个可以吗?显然,我也可以在客户端存储盐,但是如果用户从另一部手机登录,他必须能够检索盐。

        替代方法是以明文发送密码并处理服务器端的所有salting和散列。我会使用HTTPS。

        哪种方法更可取?我还缺少第三个吗?

2 个答案:

答案 0 :(得分:3)

  

显然,这种方法的周点是攻击者可以毫不费力地为任何用户看到盐。

不,缺点是您的服务器信任客户端。以下是MSDN对情况的简要介绍:

  

您永远不应该直接信任用户输入,尤其是在用户输入是匿名的情况下。请记住两条黄金法则:永远不要信任用户输入,并始终在数据从不受信任的域移动到受信任域时检查数据。

来源:Do Not Trust User Input Directly

此处您有用户数据从不受信任的客户端移动到您的服务器。您需要验证服务器上的输入。通过在客户端上执行盐的生成和密码哈希,可以防止任何攻击。保护服务器 - 客户端通信的唯一方法是使用非对称加密的安全握手密钥交换。这通过HTTPS发生,一旦链接是安全的,那么以纯文本发送密码与将代码发送到客户端以执行散列客户端一样危险。

如果您不使用HTTPS保护与客户端的连接,则您总是容易受到中间人攻击。即使密码在返回到您的服务器时名义上是模糊的,攻击者也可以将您的服务器模拟到客户端,发送一个跳过哈希的HTML表单或者以明文形式将密码发送到他们的服务器。

在您的方案中暴露盐是一个额外的安全漏洞,但在明显的漏洞旁边,它会让攻击者直接获取密码。如果你愿意,我可以进一步解释这种攻击,但除​​非密码本身得到更好的保护,否则它是一种完全没有意义的攻击;一旦发生这种情况,你就不需要首先暴露盐了。


回应评论,如果您确定盐是正确生成的,那么盐可以在不降低安全性的情况下公开发布。对于盐,这意味着它们具有足够的长度,足够随机,并且在某些方案中它们是cryptographically secure。问题是你允许客户端生成盐,这意味着,我认为我们现在都同意,他们不可信任。也许攻击者破坏了您依赖PRNG的外部库。也许某些用户设备的entropy pool不足。也许他们的设备对side-channel attacks不安全。如果您正在制作Android应用程序,肯定会有一些非常不安全的设备。在Apple的围墙花园中,这些风险可能会低得可怜,但你永远无法消除它们。

然而,就像我原先说的那样,这些风险在您的计划的真正危险之后是微不足道的。也就是说,您将以明文形式传递的散列传输到您的服务器。即使您在将其存储到数据库之前进一步散列它,因此SQL注入不能只转储所有用户密码,您仍然容易受到中间人攻击。未经加密的HTTP流量可由其通过的任何路由器观察和记录。一旦攻击者观察到哈希密码,他们就可以将相同的请求重新发送到您的服务器,并进行不正确的身份验证。

答案 1 :(得分:3)

您应该严格选择“以明文方式发送密码并处理服务器端的所有salting和散列。我会使用HTTPS。”

当然上面的句子是高度矛盾的:如果您使用HTTPS,那么密码将不是纯文本。您应该使用HTTPS。

在服务器上,您可以将随机生成的盐作为明文存储在数据库中。您不应该选择普通哈希,而是选择密码哈希 - 例如由PBKDF2生成的哈希 - 而不是。

如果您的数据库被盗,盐就在那里:盐将确保相同的密码不会被发现相同。此外,盐将无法使用预计算密码哈希值 rainbow tables

需要注意的两件重要事项:对于Web客户端,您必须依赖受信任的TLS证书存储来创建安全的TLS连接。此外,您的客户可能无法访问一个好的随机数生成器。