folm/random_compat

PHP 5.x 版本的 random_bytes() 和 random_int() 多版本兼容库,由 PHP 7 提供

v2.0.18 2018-11-27 13:55 UTC

README

Build Status Scrutinizer Latest Stable Version Latest Unstable Version License Downloads

PHP 5.x 版本的 random_bytes()random_int() 多版本兼容库由 Paragon Initiative Enterprises 创建和维护。

虽然这个库应该在更早版本的 PHP 中也能工作,但我们只考虑与支持的 PHP 版本相关的 issue。如果正在使用不受支持的 PHP 版本,请尽快升级。

重要

尽管这个库已经由 PHP 社区的一些安全专家检查过,但仍然有可能忽略某些内容。在考虑在生产环境中部署它之前,请让您的信任黑客检查其实施错误和漏洞。

不要使用 master 分支,请使用稳定版本

关于这个库的背景,请参考我们关于在 PHP 中安全生成随机整数和字符串的博客文章。

可用性说明

如果 PHP 无法安全地生成随机数据,则此库将抛出 Exception。它永远不会回退到不安全的随机数据。如果这种情况持续发生,请立即升级到较新的 PHP 版本。

安装

使用Composer

# For libraries and frameworks that support PHP 5 but may be used by
# other software that only supports PHP 7:
composer require paragonie/random_compat:\>=2

# For software that explicitly needs PHP 5 support:
composer require paragonie/random_compat:\<9.99

签名 PHP 存档

从版本 1.2.0 开始,我们还在 Github 上的每个稳定版本中提供 ECDSA 签名的 PHP Archive。

  1. 下载.phar.phar.pubkey.phar.pubkey.asc文件。
  2. (推荐但不强制) 使用Paragon Initiative Enterprises 的 PGP 公钥验证.phar.pubkey的 PGP 签名(包含在.asc文件中)。
  3. .phar.phar.pubkey文件提取到同一目录。
  4. require_once "/path/to/random_compat.phar";
  5. 当发布新版本时,您只需替换.phar文件;.pubkey不会更改(除非我们的签名密钥受到损害)。

手动安装

  1. 下载稳定版本
  2. 将文件提取到您的项目中。
  3. require_once "/path/to/random_compat/lib/random.php";

入口应该是 lib/random.php,而不是/lib中的其他任何文件。

使用方法

此库公开了 PHP 7 中添加的 CSPRNG 函数,以便在 PHP 5 项目中使用。它们的行为应该是一致的。

生成一个随机字节字符串

try {
    $string = random_bytes(32);
} catch (TypeError $e) {
    // Well, it's an integer, so this IS unexpected.
    die("An unexpected error has occurred"); 
} catch (Error $e) {
    // This is also unexpected because 32 is a reasonable integer.
    die("An unexpected error has occurred");
} catch (Exception $e) {
    // If you get this message, the CSPRNG failed hard.
    die("Could not generate a random string. Is our OS secure?");
}

var_dump(bin2hex($string));
// string(64) "5787c41ae124b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2eeac6f"

生成两个给定整数之间的随机整数(包括两个整数)

try {
    $int = random_int(0, 255);
} catch (TypeError $e) {
    // Well, it's an integer, so this IS unexpected.
    die("An unexpected error has occurred"); 
} catch (Error $e) {
    // This is also unexpected because 0 and 255 are both reasonable integers.
    die("An unexpected error has occurred");
} catch (Exception $e) {
    // If you get this message, the CSPRNG failed hard.
    die("Could not generate a random int. Is our OS secure?");
}

var_dump($int);
// int(47)

异常处理

在处理异常和错误时,必须考虑到 PHP 5 和 PHP7 之间的差异。

差异

  • 在捕获 Error 时,只要在捕获 Exception 之前,就可以正常工作。
  • 在没有之前捕获 Error 的情况下,捕获 Exception 具有不同的行为。
  • 没有通用的方法来捕获所有错误/异常。

我们的建议

始终在捕获 Exception 之前捕获 Error

示例

try {
    return random_int(1, $userInput);
} catch (TypeError $e) {
    // This is okay, so long as `Error` is caught before `Exception`.
    throw new Exception('Please enter a number!');
} catch (Error $e) {
    // This is required, if you do not need to do anything just rethrow.
    throw $e;
} catch (Exception $e) {
    // This is optional and maybe omitted if you do not want to handle errors
    // during generation.
    throw new InternalServerErrorException(
        'Oops, our server is bust and cannot generate any random data.',
        500,
        $e
    );
}

故障排除

异常:"无法收集足够的随机数据"

如果抛出异常,则表示您的操作系统不安全。

  1. 如果您使用的是Windows,请确保已启用mcrypt。
  2. 如果您使用的是其他操作系统,请确保/dev/urandom可读。
    • FreeBSD监狱需要从主机操作系统公开/dev/urandom
    • 如果您使用open_basedir,请确保/dev/urandom被允许

此库不(也不会接受任何回退到不安全随机数生成器的补丁)。

与[其他PHP项目]版本冲突

如果您正在使用在其composer.json中包含如下行的一个项目

"require" {
    ...
    "paragonie/random_compat": "~1.1",
    ...
}

...然后您尝试添加random_compat 2(或另一个显式要求random_compat 2的库,例如这个安全的PHP加密库),您将遇到版本冲突。

解决方案是让项目更新其需求字符串,以允许使用2及以上版本,而不是将用户硬锁定在版本1。

"require" {
    ...
-    "paragonie/random_compat": "~1.1",
+    "paragonie/random_compat": ">=1",
    ...
}

版本9.99.99

注意:有一个特殊版本称为9.99.99,它使此库不执行任何操作,但只能在PHP 7上安装。

如果您正在编写支持PHP 5的软件(例如库),但可能被不支持PHP 5的软件使用,您希望允许安装9.99.99。上面的diff就是您想要的。

相反,如果您正在编写的软件(本身)支持PHP 5,您不希望安装9.99.99,因此您希望进行以下更改

"require" {
    ...
-    "paragonie/random_compat": "~1.1",
+    "paragonie/random_compat": ">=1 <9.99",
    ...
}

为了避免安装“空”版本9.99.99,您可以在根composer.json中添加replace部分

"replace": {
    "paragonie/random_compat": "9.99.99"
},

清单读取长度错误

如果您使用的是PHP Archive(Phar)方法而不是Composer,并且您收到类似“清单读取长度为{int1}应该是{int2}”的错误消息,则Phar扩展可能未启用。

请参阅此评论以获取有关如何解决此问题的具体指导。

贡献者

如果没有以下个人的贡献,该项目将远远达不到今天的水平