我维护的网站已经生产了 3 年。当您注册时,该网站会为您生成一个大的(20 位)随机十六进制密码。它以未加盐的 MD5 散列存储。
当我告诉首席开发人员 MD5 对密码不利时,他说如果坏人得到它,他们就无法破解它,因为密码是随机的。即使坏人破解了它,我们也会生成它,这样用户就不能在其他网站上重复使用它。
我怎样才能说服他我们需要使用最佳实践?他很固执...
我维护的网站已经生产了 3 年。当您注册时,该网站会为您生成一个大的(20 位)随机十六进制密码。它以未加盐的 MD5 散列存储。
当我告诉首席开发人员 MD5 对密码不利时,他说如果坏人得到它,他们就无法破解它,因为密码是随机的。即使坏人破解了它,我们也会生成它,这样用户就不能在其他网站上重复使用它。
我怎样才能说服他我们需要使用最佳实践?他很固执...
好的,所以网站在注册时为每个用户生成一个随机密码。一个重要的问题是用户是否可以稍后手动设置密码,或者他们是否被迫使用随机站点生成的密码。让我们分别来看这两种情况。
据我所知,这是您在问题中描述的场景。不幸的是,您的开发人员(大部分)是正确的。至少关于散列的单次迭代与大的慢散列。您的问题有点盲目地应用“最佳实践”而不考虑这些实践的目的。对于这方面的一个很好的例子,这是一个很好的阅读:
切换MD5
到SHA256
,可能会添加每个用户的盐,并且可能考虑使用 32 字符密码。但是添加一个大的慢散列函数会增加你的服务器负载,几乎没有增加安全性(至少禁止你的实现中的任何其他错误)。
窃取您的数据库的暴力攻击者破解密码哈希所需的工作量大致为:
entropy_of_password * number_of_hash_iterations * slowness_of_hash_function
其中entropy_of_password
是可能性的数量,或密码的“可猜测性”。只要这个“公式”高于 128 位熵(或等效的工作因子/要执行的哈希指令的数量),那么你就很好。对于用户选择的密码,entropy_of_password
它非常低,因此您需要对一个非常慢的散列函数(例如PBKDF2
or scrypt
)进行大量迭代(例如 100,000 次)才能提高工作系数。
“20 位十六进制数字”我假设您的意思是有 16 20 = 2 80 个可能的密码,低于“最佳实践” 2 128,但除非您是政府或银行,否则您可能有足够的蛮力- 仅从密码的熵中强制安全。
盐在这里也没有任何用处,因为预先计算所有哈希就像 2 80 * 32 位/哈希,大约是 1 ZB(或5000 x 地球上所有硬盘驱动器的总容量)。彩虹表对此有所帮助,但坦率地说,任何有能力做到这一点的攻击者都应该拥有我们所有人。
您仍然希望对密码进行哈希处理以防止攻击者免费离开明文,但一次哈希迭代就足够了。切换MD5
到SHA256
虽然,也许考虑使用 32 个字符的密码。
该线程的评论者似乎痴迷于这样的想法,即尽管您声明该站点会生成密码,但用户实际上可以选择自己的密码。
一旦用户有可能更改密码,单次哈希迭代就无法存储现在的低熵密码。在这种情况下,您是正确的,您需要为密码存储做所有最佳实践。
无论哪种方式(用户选择或随机密码),您可能都需要每个用户的盐。
如果用户选择,则盐是最佳实践的一部分。'纳夫说。
如果是随机的,@GordonDavisson 在评论[1]、[2]中指出了一个非常好的攻击,基于观察到与哈希计算相比,数据库查找基本上是免费的。计算哈希并将其与所有用户的哈希进行比较与将其与特定用户的哈希进行比较的成本基本相同。只要您乐于进入任何帐户(而不是试图破解特定帐户),那么系统中的用户越多,攻击的效率就越高。
例如,假设您窃取了具有一百万个帐户(大约 2 20)的系统的未加盐哈希密码数据库。对于 2 20 个帐户,您从统计上预计会在前 2 60次猜测中获得成功。您仍在进行 O(2 80 )猜测,但 O(2 60 ) 散列 * O(2 20 ) db 查找 ~= O(2 60 ) 散列。
每用户盐是防止攻击所有用户的唯一方法,代价是攻击一个用户。
补充Mike Ounsworth的答案,您的开发人员可能是正确的,前提是他们正确生成了随机数。
如果您为生成这些密码的 PRNG 植入了错误的种子,那么攻击者可以推断您的 PRNG 的状态以预测未来的密码。例如,在一个非常病态的情况下,您使用 Mersenne Twister 的内部状态在会话之间不刷新,以下攻击是可行的:
确保使用加密安全的随机源。您的语言的内置 PRNG 可能不是。
此外,您的用户实际上将如何记住这些密码?生成冗长且不可预测的内容只会让您的用户password.txt
在他们的桌面上进行保存。如果密码打算存储在某个配置文件中,那么您可能没有任何真正的问题,但是如果它应该存在于用户的脑海中,那么您就大大高估了用户的能力,并且很可能导致他们发明自己的安全漏洞。
正如其他人所说,反转 80 位随机数的 MD5 是一个难题,因此如果有人获得了您的哈希表,他们可能无法访问用户帐户。
但是,您可能需要考虑用户存储这些 80 位随机数的位置。它可能不会出现在他们的脑海中。最好的情况是,它位于相当安全的钥匙串或密码存储库应用程序中。最坏的情况是,他们的主目录中会有一个带有 PASSWORDS_FOR_YER_APP.TXT 的文件。
正如您所说的 MD5 是不安全的,主要是因为 2013 年的发现允许它在 2^18 时间内受到碰撞攻击(在现代机器上显然不到一秒)。
无论密码是否将在其他网站上使用,您的网站仍然不安全。仅仅因为它是随机的,因此不会出现在任何类型的查找表中,并不意味着它不能通过碰撞破坏。这意味着如果有人获得了哈希,他们可以很容易地确定可以用作密码的东西,假设您检查了哈希。
正如其他人所说,使用更好的方法 - SHA 系列很好,但许多人更喜欢 SCrypt 和 BCrypt 作为密码,如果你处理的是随机生成的密码,你可能不需要加盐。