我正在开发一个PHP 5.4的网站,我想知道哪个更好用于生成密码安全的随机盐?
$salt = sha1(openssl_random_pseudo_bytes(23));
或
$seed = '';
$a = @fopen('/dev/urandom','rb');
$seed .= @fread($a,23);
$salt = sha1(seed);
或者我应该选择:
$salt = openssl_random_pseudo_bytes(40);
或
$salt = '';
$a = @fopen('/dev/urandom','rb');
$salt .= @fread($a,23);
答案 0 :(得分:10)
出于安全考虑,最好使用openssl_random_pseudo_bytes
。 OpenSSL负责收集足够的熵,为您提供良好的随机性。 /dev/urandom
被设计为从不阻止,并且可能被欺骗为您提供不那么随机的字节。
使用随机字节,您无需通过SHA1运行它们。
总结一下,做:
$salt = openssl_random_pseudo_bytes(40, $cstrong);
if (! $cstrong) {
exit('This should not happen');
}
答案 1 :(得分:9)
在实践中,几乎肯定没有区别。
openssl_random_pseudo_bytes
和/dev/urandom
都提供加密安全的伪随机字节源。两者都不保证真正随机,但在实践中,预计两者都无法通过任何已知或可预见的技术与真正的随机性区分开来。
Kmkaplan在技术上是正确的,注意/dev/urandom
在某些条件下可以返回理论上可预测的输出,如man unrandom
中所述:
“从 / dev / urandom 设备读取不会阻止等待更多熵。因此,如果熵池中没有足够的熵,则返回的值在理论上容易受到影响对驱动程序使用的算法进行加密攻击。当前未分类的文献中没有关于如何执行此操作的知识,但理论上可能存在此类攻击。如果这是您应用程序中的问题,请使用 / dev / random 而不是。“
然而,openssl_random_pseudo_bytes
(内部calls OpenSSL函数RAND_pseudo_bytes
)实际上也是如此,如OpenSSL documentation中所述:
“
RAND_pseudo_bytes()
将 num 伪随机字节放入 buf 。RAND_pseudo_bytes()
生成的伪随机字节序列将是唯一的它们具有足够的长度,但不一定是不可预测的。它们可用于非加密目的,也可用于加密协议中的某些目的,但通常不用于密钥生成等。“
这些警告中的任何一个都不应该吓到你使用这些方法 - 他们描述的弱点只是理论上的,除非可能在某些设计的情况下(例如在启动后没有硬件RNG的无盘嵌入式设备上),以及在正常部署PHP的情况下,不应该是实际问题。
结果是,这些随机数生成方法都不会在您的密码系统中the weakest link,因此您可以安全地选择其中任何一种。如果你感到偏执,你甚至可以同时使用它们。
聚苯乙烯。 openssl_random_pseudo_bytes
的一个优点是它也适用于Windows。另一方面,即使未安装OpenSSL PHP扩展,也可以在Unix上使用/dev/urandom
。因此,为了获得最大的可移植性,您确实应该实现对这两者的支持。
此外,请始终检查您确实收到了预期的字节数;例如,上述问题中基于/dev/urandom
的代码可以在Windows不存在/dev/urandom
的系统上静默返回空字符串。