仅将电子邮件地址存储为哈希值是个好主意吗?

信息安全 密码 哈希
2021-08-20 16:13:00

我目前正在http://write-math.com上构建一个类似于http://detexify.kirelabs.org/的 Web 服务,它应该可以帮助用户从绘制的公式中获取 LaTeX 代码。这是我的学士论文的一部分,这个项目的主要目标是让在线手写识别领域的研究变得更容易。这意味着我想分享我从用户那里获得的所有数据。

最简单的方法是简单地转储数据库。这样,我可以一步完成备份副本和转储给研究人员。

只要其他用户使用我的系统,我就不愿与公众分享它的两个部分:电子邮件地址和密码。

密码

密码存储哈希和加盐(这意味着我存储md5($userpass.$salt)$salt这是一个 8 个字符的随机字符串,其中的字符来自A-Za-z0-9- 为每个用户生成盐)。这是否足以让公开它是可以的?

问题的主要部分是关于电子邮件地址:目前,我将其存储为纯文本。但我正在考虑仅存储电子邮件地址的哈希值。这个哈希不能加盐,因为我的登录功能如下:

用户输入$email$password两者都以纯文本形式发送到服务器。然后服务器执行(作为伪代码):

$pwdb, $salt = query(SELECT password, salt FROM users WHERE email = :email)
if (md5($password.$salt) == $pwdb) {
   Logged in
} else {
   Wrong password
}

电子邮件地址

:email$emailmd5($email)无关紧要md5($email.$applicationwide_random_str)但是我不能在不经过每个用户的情况下为每个用户制作新的盐(当我认为我永远不会拥有超过 10,000 个用户时,这可能还不错)。

问题

  • 当您不知道随机字符串时,使用“标准”硬件(< 1000 美元)附加 8 个字符的随机盐(例如) “取消散列”一封电子邮件(例如info@martin-thoma.de或)需要多长时间?是几秒钟、几分钟、几小时还是几天的问题?mexplex@gmail.comFHCJ81ru
  • 如果人们能做到这一点,那是不是很糟糕?我的意思是他们也可以简单地发送电子邮件并查看他们返回的内容。在我的服务中,涉及的个人数据不多:
    • 手写符号和公式
    • 最终偏手
    • 最终何时/何地学习写作
    • 最终用户的语言
  • 为什么没有服务对电子邮件地址进行散列(好吧,我不知道是否没有这样做的服务,但我从未读过 - 散列密码很常见,但散列电子邮件地址?从未听说过。)
  • 如果您只想在用户丢失密码并登录时才使用电子邮件,那么散列电子邮件是否是个好主意?(我虽然关于使用 OpenID,但大多数人不知道它是什么)
2个回答

最后,有两个问题:你应该存储什么,以及你应该分享什么。

你应该存储什么

存储电子邮件地址的好处是您可以联系用户。许多网站确实希望能够联系当前未登录的用户。例如,商家网站希望能够通知用户他们的订单已发送或他们的付款被退回。许多网站都有可配置的电子邮件通知。网站可能希望通知用户隐私或安全漏洞——人们往往更喜欢私下通知而不是在新闻中得知。这还不包括所有恶意目的(发送---垃圾邮件---“促销优惠”)。

如果您决定永远不需要联系用户,请存储(缓慢且加盐!不是 MD5 或 SHA-2,而是 PBKDF2 或 bcrypt 或 scrypt。)电子邮件的哈希值。但请注意这些限制。

我假设您将使用电子邮件地址作为用户唯一标识符。这有一个缺点:有时人们会更改电子邮件。例如,在学术界(很多用户可能属于),人们经常使用他们当前机构的电子邮件,然后第二年这封电子邮件变得无法使用。这可以将他们与与电子邮件地址联系得太紧密的帐户隔离开来。确保允许一种转换方式(如果您需要访问旧电子邮件地址来添加新地址,这可能会很棘手)。

你应该分享什么

暴力破解加盐哈希需要枚举所有可能性。尝试一种可能性所需的时间是慢散列的配置参数——你应该让它尽可能慢,只要你的服务器支持,但不要更慢。因此,“取消散列”一封电子邮件需要多长时间”的答案实际上是“无论您选择什么”。

无论如何,暴力破解您的电子邮件数据库需要多长时间并不是真正的决定性问题。验证电子邮件是否在您的数据库中显然是可行的——您的服务器将一直这样做——这允许知道哈希的人回答“Bob 有帐户吗?”的问题。这已经是侵犯隐私了。

密码也是如此:即使允许第三方检查他们对 Bob 密码的猜测也是不好的。没有泄露 Bob 的密码那么糟糕,但仍然很糟糕。

所以简单的答案是:不要将电子邮件地址或密码以及它们的哈希值传达给第三方。如果您不小心泄露了哈希值,这就是隐私泄露。共享数据时,请为用户帐户使用无意义的标识符,例如顺序 ID 或随机 UUID。

还要注意数据库中的范围蔓延。如果您存储了太多关于用户的信息,这可能会导致识别和建立联系。这是医学数据库的一个常见问题——如果你碰巧知道 Alice 从 1997 年 2 月 25 日到 1997 年 3 月 3 日和 2001 年 7 月 21 日到 2001 年 7 月 28 日在河滨医院,并且有一个1997 年 2 月入院河滨医院,3 月离开,2001 年 7 月再次入院的单一病历——即使她的名字从未暴露,爱丽丝已被确认身份。这可能与您现在计划存储的信息无关,但请记住这一点。

永远不要导出任何用户数据,即使是散列形式,也可能有人会想办法破解加密/散列。

所以只导出相关数据表,不导出用户表。您的数据中将包含外键引用,因此您知道哪些项目属于同一用户,但对于使用转储数据的人来说,这将是一个匿名数字帐户。