将安全用户名存储在数据库中

时间:2017-05-04 02:00:24

标签: security encryption hash username hash-collision

我想保护我的用户'在线服务中的用户名,因为它可能是个人识别(例如,电子邮件地址),但我想知道它是否可能......

我的第一个倾向是哈希(无盐),但我担心可能的哈希碰撞。并没有太多担心SHA256 32位散列中发生冲突的可能性,而是更多地关注使用的用户名类可能只是容易发生冲突的可能性。

我也研究过完美的哈希值,但由于用户可以动态添加,因此管理起来太难了。

我想到的另一个选择是(当添加用户时)如果存在哈希冲突,我会回复客户端请求另一个哈希,并重复直到没有冲突。我在登录期间重复此过程。但是,我也想知道这是否真的让攻击者更容易,因为他们对哈希成功的反馈有更多的反馈,如果数据库遭到入侵,所有额外的哈希将使得恢复原始值更容易。

我还在考虑使用用户名作为密码来加密用户名,但我猜这也会受到冲突的影响(因为每个条目都有一个唯一的密码 - 两个不同的明文可能会产生两个不同的密码在相同的密文中),所以我认为它不值得进一步探索。

我真的不想使用自定义用户名(用户必须提出在注册时没有采取的内容),因为我期待用户很少使用该服务,可能会忘记他们的用户名。

我目前以为我会先考虑一次哈希的第一个想法,如果发生碰撞,请确定密码(希望那里也没有碰撞) - 我可以把当用户注册表示不允许使用他们的用户名/密码时会发出警告,因为它会将其作为另一个用户/ / S登录。

是否存在创建安全形式的用户名的非碰撞方式?

谢谢。

1 个答案:

答案 0 :(得分:0)

假设我们正在谈论电子邮件,因为没有其他许多选项可用于登录名。

  

我还在考虑使用用户名作为密码来加密用户名,但我猜这也会受到冲突的影响(因为每个条目都有一个唯一的密码 - 两个不同的明文可能会产生两个不同的密码在相同的密文中),所以我认为它不值得进一步探索。

这里的碰撞是错误的,在这里担心......

强制免责声明:加密密钥与密码不同。并且以自身为关键加密plainText甚至更糟。

加密的问题是cipherTexts是不可搜索的;即,您无法验证唯一性,除非您每次都解密所有用户记录,因此这是不可持续的 - 您的服务器负载将随着每个新用户记录呈指数级增长。
这是因为虽然加密使用了IV(初始化向量;即相当于密码哈希中的盐),但即使您使用相同的密钥对同一个plainText进行两次加密,也会产生不同的cipherText。

但是,您很可能需要加密这些电子邮件,就像您需要发送密码重置链接,通知等一样 - 您需要双向机制。你不能用哈希来做这些事情,因为它们只是单向的 这就是每个网站将其用户帐户与电子邮件地址相关联的原因,即使它们不是登录名。 :)

仅为登录检查所做的是存储电子邮件的HMAC(基于哈希的消息验证码)。

HMAC看起来就像常规哈希,但实际上是"键入哈希" (即,您将在散列时使用密钥,类似于加密)。除此之外,到目前为止,没有人设法找到与HMAC构造的碰撞,即使是现在着名的不安全MD5(仍然请使用现代算法;至少是SHA-2)。

我应该注意,HMAC并不像密码哈希算法那样强大,因此您的用户电子邮件肯定不会像密码一样受到强烈保护,但它不像那里的那样#39 ;你可以做任何其他事情,它应该没问题。

总之,您需要在应用程序中配置两个单独的加密密钥 - 一个用于加密,一个用于HMAC - 并存储以下数据:

  • userLoginLookup - 电子邮件的HMAC,使用两个密钥之一
  • userLoginMailer - 电子邮件的cipherText,使用第二个配置的密钥
  • userPassword - 标准密码哈希;使用bcrypt,PBKDF2或scrypt

注意:加密始终区分大小写,因此为了适应查找,您需要始终首先规范化电子邮件地址;即将它们全小写或全大写。

当用户尝试登录时,您执行HMAC(emailInput, hmacKey)并搜索与数据库中userLoginLookup字段的匹配项。

当您需要发送通知或密码重置电子邮件时,您解密了userLoginMailer