intelogie/random_compat

PHP 5.x 的 random_bytes() 和 random_int() 多版本兼容层,源自 PHP 7

v2.0.2 2016-04-03 06:00 UTC

README

Build Status Scrutinizer

由 Paragon Initiative Enterprises 创建和维护的 PHP 5.x 的 random_bytes() 和 random_int() 多版本兼容层,用于在 PHP 7 中实现。

尽管这个库在早期版本的 PHP 中也能运行,但我们只会考虑与支持版本相关的性问题。如果您正在使用不受支持的 PHP 版本,请尽快升级。

重要

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

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

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

可用性通知

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

安装

使用Composer

composer require paragonie/random_compat

签名 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";

用法

此库公开了 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 之前。
  • 捕获 Exception 的行为与之前捕获 Error 不同。
  • 没有可移植的方式来捕获所有错误/异常。

我们的建议

始终在捕获 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

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

贡献者

如果不是以下个人的贡献,这个项目将远远达不到今天这样的优秀水平