多少位熵将
SELECT SHA2(RAND(), 256);
产生?
(实际问题:这是为密码生成随机盐的合理方法吗?)
让我们分解一下。
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-compat或phpass。
在其他语言中,我不确定。但说真的,不要重新发明它。只需使用一个库(最好是使用 bcrypt 或 scrypt 的库)并完成它。
散列函数 SHA2 不会对结果盐添加任何熵,它只是将结果rand()
带入另一种形式。这意味着,一切都取决于rand()
功能及其实现。
函数rand()
当然不是随机的,如果知道函数的状态(最后的结果),就可以预测下一个生成的值。状态本身基于一个种子,有时这个种子是由应用程序自动设置的。例如,PHP 从当前时间和进程 ID 创建一个种子。请注意,这些值在某种程度上也是可以预测的,或者至少会缩小可能结果的范围。
我不知道 rand 的 MYSQL 实现,但我不建议使用它的rand()
函数来生成盐。实际上,我永远不会让数据库生成密码的盐值或哈希值,因为大多数数据库都没有提供适当的方法来哈希密码。而是使用具有慢速密钥派生功能的开发环境,例如BCrypt,此类功能通常会自动创建安全的盐。
要回答您的问题,唯一性是盐的主要目的,因此产生盐的方法较弱。更好的是一种不可预测的盐,因此没有人可以预先计算盐(可能的盐的范围),因此可以准备攻击。获得盐的最佳方法是使用操作系统的随机源 (URANDOM)。