什么应该用作盐?

信息安全 密码 密码管理
2021-08-19 16:13:07

我总是听说最好在存储的密码之上使用盐,然后以某种方式将其连接起来并在之后进行哈希处理。但我不知道用什么做盐。什么是好盐?

4个回答

用于密码散列的盐的经典建议是:

  • 128位或更多的随机值
  • 从加密健全的随机数生成器(/dev/random/dev/urandom现代 Unix 上)获得;
  • 每个条目都是唯一的(即不要重复使用相同的盐,为每个新密码生成一个新的盐);
  • 以明文形式存储在数据库中(以便在验证哈希时可以使用盐)。

过去有很多相关主题的讨论。最重要的是,您不应该实现自己的密码哈希方案——您应该使用经过验证、经过良好测试、同行评审的实现 (bcrypt/PBKDF2)

假设您有一个表,您将在其中存储每个人的密码。

要“保存”正在生成的密码,请执行以下操作

  1. 从用户那里获取登录信息
  2. 获取密码
  3. 从随机值生成一些盐。假设,从 /dev/random (正如@Michal 建议的那样),你得到了“a12bc34de56fg”
  4. 使用一些散列函数来生成散列密码。假设原始密码是“1password”,您将使用任何 SHA 散列。你会做

hashed_pa​​ssword = SHA(SHA(SHA(.... SHA("1passworda12bc34de56fg"))))))))

将该 hashed_pa​​ssword 与登录名和 salt 一起存储在表中。

login      password      salt
--------------------------------------
john       a7b82783...   a12bc34de56fg

然后,验证用户何时访问您的应用程序:

  1. 获取登录名和密码
  2. 从数据库中检索该登录的盐(您将拥有盐:a12bc34de56fg)
  3. 将纯文本密码与盐连接起来,然后再次进行所有散列:

hashed_pa​​ssword = SHA(SHA(SHA(.... SHA("1passworda12bc34de56fg"))))))))

验证您计算的 hashed_pa​​ssword 是否与存储在数据库中的相同。你会知道密码是否正确。

而已!。你可以从任何你喜欢的随机来源获得盐。为什么它应该是随机的?因为任何非随机盐都会使尝试暴力破解您的应用程序变得更加容易。

答案是“几乎任何东西”,尽管有些人比其他人更强大。

假设您使用的是 md5(salt.password)。

没有盐,黑客只需在彩虹表中查找哈希值,就可以快速破解大部分密码。

假设您使用“x”作为所有密码的盐。您的许多密码仍会被发现,但会更少。那是因为如果密码是“p4ssw0rd”,那么它会变成“xp4ssw0rd”,加了盐——稍微难一点,但不是很明显。

现在假设您使用“%X88Fc+7”作为所有密码的一种盐。在这一点上,彩虹表不起作用。但是,对所有密码使用一种盐的结果是,黑客将能够根据该假设生成彩虹表,并提前构建彩虹表。它更安全,但并不完美。

下一个最安全的选项是使用用户名作为盐,换句话说,使用“md5(username.password)”。同样,这破坏了标准彩虹表,但黑客可能会为特定用户名(如“root”或“管理员”)生成彩虹表,因此每次更改密码时,黑客都可以查看彩虹表表而不是再次破解它。

因此,为了更加安全,请为不同的用户选择不同的随机盐。您必须将其与用户名和密码哈希一起存储。这完全击败了彩虹表。

有些人建议使用“安全”随机数生成器,而不是简单的东西。例如,在用户创建帐户时执行 MD5(时间戳+用户名)很简单,但在密码学上并不安全(因为时间戳和用户名是可预测的,因此熵很低)。但是,由于黑客在窃取数据库时无论如何都有盐的副本,所以这不是问题。

对于盐,只需使用随机位。

在 Linux 上,您可以使用/dev/urandom. 它是一种基于环境噪声的随机数生成器。除了虚拟机之外,这是非常不可预测的。因此,如果您假设将物理鼠标插入您的盒子,那么/dev/urandom将为您提供高质量的随机位并且对盐有好处。

这是一篇很好的文章另请参阅外部参考。

这是一个示例 java 代码在函数中查看盐是如何生成和存储在 DB 中的createUser()除了使用import sun.misc. ...它是非常好的代码。