2012-12-30 302 views
9

我正在PHP 5.4中开发一个站点,我想知道哪个更好用来创建密码安全的随机盐?我应该使用urandom还是openssl_random_pseudo_bytes?

$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); 
+4

使用'SHA1()'将大大降低你的随机盐的有效性,因为这将其转换成字符串,它是40个字符,并仅含有0-9和A-F的字符。会有少了很多组合(意为随机的),比如果你只是使用40个字节'openssl_random_pseudo_bytes()' –

+0

我与您的两个建议去 – John

回答

10

为了安全起见,你最好使用openssl_random_pseudo_bytes。 OpenSSL负责收集足够的熵来为您提供良好的随机性。 /dev/urandom被设计为从来没有块,并可能欺骗,让你没有这么随机的字节。

随机字节您不需要通过SHA1运行它们。

总之这一切,做到:

$salt = openssl_random_pseudo_bytes(40, $cstrong); 
if (! $cstrong) { 
    exit('This should not happen'); 
} 
+1

事实上,'openssl_rand_pseudo_bytes'没有任何_guarantee_真正的随机性,任何更多比'/ dev/urandom'确实;这就是名字中的'pseudo'意思。然而,在实践中,两者都通过任何已知的手段产生无法区分的和随机的。 –

+0

@IlmariKaronen当然,你不会得到真正的随机性。我只写了“好”; OpenSSL称之为“密码强大”。这就是为什么我在测试中检查结果是否具有密码强度。 – kmkaplan

+1

[不要使用OpenSSL](https://github.com/ramsey/uuid/issues/80)。 –

9

在实践中,几乎可以肯定是没有什么区别。

openssl_random_pseudo_bytes/dev/urandom都提供了密码安全的伪随机字节源。它们都不是随机的,但实际上,它们都可以通过任何已知或可预见的技术与真正的随机性区分开来。

Kmkaplan是在指出的是/dev/urandom可以在一定条件下返回理论上预测的输出,如在man unrandom指出技术上正确:

“从的/ dev/urandom的装置的读不会阻塞等待更多因此,如果熵池中没有足够的熵,则返回的值在理论上容易受到对驾驶员所用算法的加密攻击,在当前未分类的文献中不知道如何做到这一点,但理论上可能存在这样的攻击,如果这是你应用中的一个问题n,改为使用/dev/random。“

然而,同样是openssl_random_pseudo_bytes(其calls OpenSSL的功能RAND_pseudo_bytes内部)实际上的确,正如在OpenSSL documentation注意到:

RAND_pseudo_bytes()提出NUM伪随机字节到BUF。由RAND_pseudo_bytes()生成的伪随机字节序列如果长度足够,但不一定是不可预知的,则它们将是唯一的。它们可以用于非加密目的以及用于某些目的ptographic协议,但通常不用于密钥生成等。“

无论这些警告实际上应该吓唬你使用这些方法—他们描述仅仅是理论上的,除了可能在某些人为的情况下(如与boot-后没有硬件RNG无盘嵌入式设备上的弱点以上),不应在以下情况下的实际关注,其中PHP通常部署的。

的结果是,没有这些随机数产生方法将是在您的密码the weakest link,所以你可以放心地选择任何一个。如果你感到偏执,你甚至可以同时使用。


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

此外,经常检查你预计你确实收到许多字节;例如,上述问题中基于/dev/urandom的代码可能会在不存在/dev/urandom的Windows系统上以无提示方式返回空字符串。

+0

'RAND_pseudo_bytes'和'openssl_random_pseudo_bytes'返回一个代码,告诉你“如果生成的字节是密码强的”。 – kmkaplan

相关问题