2

多少位熵将

SELECT SHA2(RAND(), 256);

产生?

(实际问题:这是为密码生成随机盐的合理方法吗?)

4

2 回答 2

5

让我们分解一下。

SHA2 可以参考 4 种算法之一:

  • SHA224- 224 位输出
  • SHA256- 256 位输出
  • SHA384- 384 位输出
  • SHA512- 512 位输出

因此,它们每个都采用任意输入(0 到 2^64-1 位数据),并产生固定大小的输出。

请注意,这里实际上没有创建熵。然而,当输入超过输出大小的熵位时,一些会被破坏。当我们考虑到碰撞的(小)可能性时,有时小于输出大小的输入可能会破坏熵。因此,我们可以说每个函数都将熵的上限作为其输出大小。

所以散列不能增加熵。这意味着我们的熵上限是散列的输出大小和输入大小中的较小者。

现在,您的输入是RAND(). 假设您指的是 MySQL 的RAND()函数,让我们看看发生了什么。该RAND()函数产生一个浮点结果。FLOAT现在,MySQL 对数据类型使用 4 字节浮点值。这意味着,结果最多包含 32 位熵。

因此,该组合已经下降到32 位熵的上限

多亏了生日悖论,在 32 位熵下,我们有 50% 的机会在 7,000 代中发生碰撞。这对于有效的盐来说太低了......

这甚至没有触及可预测的事实RAND()(就盐而言,这不是世界末日)。

相反,只需使用一个库来为您处理生成。在 PHP 中,我建议使用 password-compatphpass

在其他语言中,我不确定。但说真的,不要重新发明它。只需使用一个库(最好是使用 bcrypt 或 scrypt 的库)并完成它。

于 2013-05-28T16:03:00.797 回答
2

散列函数 SHA2 不会对结果盐添加任何熵,它只是将结果rand()带入另一种形式。这意味着,一切都取决于rand()功能及其实现。

函数rand()当然不是随机的,如果知道函数的状态(最后的结果),就可以预测下一个生成的值。状态本身基于一个种子,有时这个种子是由应用程序自动设置的。例如,PHP 从当前时间和进程 ID 创建一个种子。请注意,这些值在某种程度上也是可以预测的,或者至少会缩小可能结果的范围。

我不知道 rand 的 MYSQL 实现,但我建议使用它的rand()函数来生成盐。实际上,我永远不会让数据库生成密码的盐值或哈希值,因为大多数数据库都没有提供适当的方法来哈希密码。而是使用具有慢速密钥派生功能的开发环境,例如BCrypt,此类功能通常会自动创建安全的盐。

要回答您的问题,唯一性是盐的主要目的,因此产生盐的方法较弱。更好的是一种不可预测的盐,因此没有人可以预先计算盐(可能的盐的范围),因此可以准备攻击。获得盐的最佳方法是使用操作系统的随机源 (URANDOM)。

于 2013-05-27T07:28:29.867 回答