【问题标题】:should i use urandom or openssl_random_pseudo_bytes?我应该使用 urandom 还是 openssl_random_pseudo_bytes?
【发布时间】:2012-12-14 21:35:39
【问题描述】:

我正在用 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);

【问题讨论】:

  • 使用sha1() 将大大降低随机盐的有效性,因为它会将其转换为40 个字符且仅包含0-9 和a-f 字符的字符串。与仅使用来自openssl_random_pseudo_bytes()的 40 个字节相比,组合会少得多(意味着随机性更少)。
  • 我同意你的两个建议

标签: php random salt


【解决方案1】:

我知道这是一篇旧帖子,但如果有人偶然发现这里是一个简单的解决方案:

compat_random.php
https://gist.github.com/anzz1/29a787fac8ef6d693b41779911287505

<?php
  require_once(dirname(__FILE__) . '/compat_random.php');

  $salt = random_bytes(40);
?>

完成。

compat_random.php 只有 2KB,62 行代码。
您应该可以将它与任何 PHP 版本一起使用。

它按以下顺序检查这些函数:

  • random_bytes (PHP >= 7) [加密安全]
  • openssl_random_pseudo_bytes (OpenSSL) [加密安全]
  • mcrypt_create_iv (php_mcrypt) [加密安全]
  • /dev/urandom(UNIX 系统)[加密安全]

很可能你确实有其中一个可用,但如果你没有,它最终会回落到

  • mt_rand() (PHP >= 4) [加密不安全,但在大多数情况下都可以]
  • rand() [不安全]

【讨论】:

    【解决方案2】:

    出于安全目的,您最好使用openssl_random_pseudo_bytes。 OpenSSL 负责收集足够的熵来为您提供良好的随机性。 /dev/urandom 被设计为从不阻塞,并且可能会被欺骗给你不那么随机的字节。

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

    总而言之,这样做:

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

    【讨论】:

    • 实际上,openssl_rand_pseudo_bytes 也不保证真正的随机性,与/dev/urandom 一样;这就是名称中的pseudo 的含义。然而,在实践中,两者都会产生无法通过任何已知方式与随机进行区分的输出。
    • @IlmariKaronen 当然你不会得到真正的随机性。我只写了“好”; OpenSSL 称之为“加密强”。这就是我进行测试以检查结果是否具有加密强度的原因。
    • @ScottArciszewski 你有什么建议作为替代方案?如果使用不正确,AFAIK /dev/urandom 也会出现问题。此外,您链接到的问题仅适用于某些服务器配置,并且已在最新版本的 PHP 中修复。我更喜欢使用经过测试并解决了任何问题的东西,并避免切换到有未知问题的替代品。
    • github.com/paragonie/random_compat - 这是 PHP 7 的安全 random_bytes() 函数的 PHP 5 polyfill。
    【解决方案3】:

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

    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 个伪随机字节放入 bufRAND_pseudo_bytes() 生成的伪随机字节序列如果足够长,则它们将是唯一的,但不一定是不可预测的。它们可以用于非加密目的和加密协议中的某些目的,但通常不能用于密钥生成等。”

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

    结果是,这两种随机数生成方法都不会在您的密码系统中成为the weakest link,因此您可以安全地选择其中任何一种。如果您感到偏执,甚至可以同时使用两者。


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

    此外,请始终检查您是否确实收到了与预期一样多的字节;例如,您上面问题中基于/dev/urandom 的代码可能会在不存在/dev/urandom 的Windows 等系统上静默返回一个空字符串。

    【讨论】:

    • RAND_pseudo_bytesopenssl_random_pseudo_bytes 返回一个代码,告诉您“生成的字节是否具有加密强度”。
    猜你喜欢
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 2015-10-16
    • 2023-03-06
    • 2013-02-20
    • 2011-07-31
    • 2010-12-23
    • 2015-05-22
    相关资源
    最近更新 更多