【问题标题】:How much entropy is there in SHA2(RAND(), 256)?SHA2(RAND(), 256) 中有多少熵?
【发布时间】:2013-05-21 21:40:46
【问题描述】:
多少位熵
SELECT SHA2(RAND(), 256);
生成?
(实际问题:这是为密码生成随机盐的合理方式吗?)
【问题讨论】:
标签:
mysql
security
passwords
salt
sha256
【解决方案1】:
让我们分解一下。
SHA2 可以参考 4 种算法之一:
-
SHA224 - 224 位输出
-
SHA256 - 256 位输出
-
SHA384 - 384 位输出
-
SHA512 - 512 位输出
因此它们每个都接受任意输入(0 到 2^64-1 位数据),并产生固定大小的输出。
请注意,这里实际上没有创建熵。然而,当输入超过输出大小的熵位时,一些会被破坏。当我们考虑到碰撞的(小)可能性时,有时小于输出大小的输入可能会破坏熵。因此,我们可以说每个函数都设置了一个熵的上限作为其输出大小。
所以散列不能增加熵。所以这意味着我们的熵上限是散列的输出大小和输入大小的较小。
现在,您的输入是 RAND()。假设您指的是 MySQL 的 RAND() 函数,让我们看看发生了什么。 RAND() 函数产生一个浮点结果。现在,MySQL 为 FLOAT 数据类型使用 4 字节浮点值。这意味着最多,结果包含 32 位熵。
因此,该组合已经下降到 32 位熵的上限。
感谢Birthday Paradox,在熵为 32 位的情况下,我们在 7,000 代中发生碰撞的几率为 50%。这对于有效的盐来说太低了......
这甚至没有触及RAND() 是可预测的事实(对于盐来说,这并不是世界末日)。
相反,只需使用库来为您处理生成。在 PHP 中,我建议使用 password-compat 或 phpass。
在其他语言中,我不确定。但说真的,不要重新发明它。只需使用一个库(最好是使用 bcrypt 或 scrypt 的库)并完成它。
【解决方案2】:
哈希函数 SHA2 不会给结果盐添加任何熵,它只是将rand() 的结果带入另一种形式。这意味着,一切都取决于rand() 函数及其实现。
函数rand()当然不是随机的,如果知道函数的状态(最后的结果),就可以预测下一个生成的值。状态本身基于一个种子,有时这个种子是由应用程序自动设置的。例如,PHP 从当前时间和进程 ID 创建一个种子。请注意,这些值在某种程度上也是可以预测的,或者至少会缩小可能结果的范围。
我不知道 rand 的 MYSQL 实现,但我不建议使用它的rand() 函数来生成盐。实际上,我永远不会让数据库生成密码的盐值或哈希值,因为大多数数据库都没有提供适当的方法来哈希密码。而是使用具有慢速密钥派生功能的开发环境,例如 BCrypt,此类功能通常会自动创建安全盐。
为了回答您的问题,唯一性是盐的主要目的,因此生成盐的方法较弱。更好的是一种不可预测的盐,因此没有人可以预先计算盐(可能的盐的范围),因此可以准备攻击。获得盐的最佳方法是使用操作系统的随机源 (URANDOM)。