我应该使用urandom还是openssl_random_pseudo_bytes?

Joh*_*ohn 9 php random salt

我正在开发一个PHP 5.4的网站,我想知道哪个更好用于生成密码安全的随机盐?

$salt = sha1(openssl_random_pseudo_bytes(23));
Run Code Online (Sandbox Code Playgroud)

要么

$seed = '';
$a = @fopen('/dev/urandom','rb');
$seed .= @fread($a,23);
$salt = sha1(seed);
Run Code Online (Sandbox Code Playgroud)

或者我应该选择:

$salt =  openssl_random_pseudo_bytes(40);
Run Code Online (Sandbox Code Playgroud)

要么

$salt = '';
$a = @fopen('/dev/urandom','rb');
$salt .= @fread($a,23);
Run Code Online (Sandbox Code Playgroud)

kmk*_*lan 10

出于安全考虑,您最好使用openssl_random_pseudo_bytes.OpenSSL负责收集足够的熵,为您提供良好的随机性./dev/urandom被设计为永远不会阻止,并可能被欺骗给你不是那么随机的字节.

使用随机字节,您无需通过SHA1运行它们.

总结一下,做:

$salt = openssl_random_pseudo_bytes(40, $cstrong);
if (! $cstrong) {
    exit('This should not happen');
}
Run Code Online (Sandbox Code Playgroud)


Ilm*_*nen 9

在实践中,几乎肯定没有区别.

双方openssl_random_pseudo_bytes/dev/urandom提供伪随机字节的加密安全源.两者都不保证是真正随机的,但在实践中,预期两者都不会被任何已知或可预见的技术与真正的随机性区分开来.

Kmkaplan在技术上是正确的,注意到/dev/urandom在某些条件下可以返回理论上可预测的输出,如下所述man unrandom:

"来自/ dev/urandom设备的读取不会阻止等待更多的熵.因此,如果熵池中没有足够的熵,则返回的值理论上容易受到驱动程序使用的算法的加密攻击.目前未分类的文献中没有关于如何做到这一点的知识,但理论上可能存在这样的攻击.如果这是您应用程序中的一个问题,请改用/ dev/random."

但是,正如OpenSSL文档中所述,实际上openssl_random_pseudo_bytes(在内部调用 OpenSSL函数RAND_pseudo_bytes)也是如此:

" RAND_pseudo_bytes()num个伪随机字节放入buf.RAND_pseudo_bytes()如果生成的伪随机字节序列长度足够,但不一定是不可预测的,它们将是唯一的.它们可用于非加密目的,并且在加密协议中用于某些目的,但通常不用于密钥生成等."

这些警告实际上都不应该吓到你使用这些方法 - 它们描述的弱点只是理论上的,除非可能在某些设计的情况下(例如在启动后没有硬件RNG的无盘嵌入式设备上),并且不应该是在正常部署PHP的情况下实际关注的问题.

结果是,这些随机数生成方法都不会成为您的密码系统中最薄弱的环节,因此您可以安全地选择其中任何一个.如果你感到偏执,你甚至可以同时使用两者.


PS.一个优点openssl_random_pseudo_bytes是它也适用于Windows.另一方面,/dev/urandom即使没有安装OpenSSL PHP扩展,也可以在Unix上使用.因此,为了实现最大的可移植性,您应该确实实现对两者的支持.

此外,始终检查您确实收到了预期的字节数; 例如,上述/dev/urandom问题中的基础代码可以在Windows等/dev/urandom不存在的系统上静默返回空字符串.