|
|
|
@ -3,12 +3,12 @@
|
|
|
|
|
* Random_* Compatibility Library
|
|
|
|
|
* for using the new PHP 7 random_* API in PHP 5 projects
|
|
|
|
|
*
|
|
|
|
|
* @version 2.0.4
|
|
|
|
|
* @released 2016-11-07
|
|
|
|
|
* @version 2.0.15
|
|
|
|
|
* @released 2018-06-08
|
|
|
|
|
*
|
|
|
|
|
* The MIT License (MIT)
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2015 - 2016 Paragon Initiative Enterprises
|
|
|
|
|
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
@ -44,18 +44,21 @@ if (!defined('PHP_VERSION_ID')) {
|
|
|
|
|
/**
|
|
|
|
|
* PHP 7.0.0 and newer have these functions natively.
|
|
|
|
|
*/
|
|
|
|
|
if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
|
|
|
|
|
if (PHP_VERSION_ID >= 70000) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
|
|
|
|
|
define('RANDOM_COMPAT_READ_BUFFER', 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$RandomCompatDIR = dirname(__FILE__);
|
|
|
|
|
$RandomCompatDIR = dirname(__FILE__);
|
|
|
|
|
|
|
|
|
|
require_once $RandomCompatDIR.'/byte_safe_strings.php';
|
|
|
|
|
require_once $RandomCompatDIR.'/cast_to_int.php';
|
|
|
|
|
require_once $RandomCompatDIR.'/error_polyfill.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'byte_safe_strings.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'cast_to_int.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'error_polyfill.php';
|
|
|
|
|
|
|
|
|
|
if (!is_callable('random_bytes')) {
|
|
|
|
|
if (!is_callable('random_bytes')) {
|
|
|
|
|
/**
|
|
|
|
|
* PHP 5.2.0 - 5.6.x way to implement random_bytes()
|
|
|
|
|
*
|
|
|
|
@ -67,16 +70,15 @@ if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
* 2. fread() /dev/urandom if available (never on Windows)
|
|
|
|
|
* 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
|
|
|
|
|
* 4. COM('CAPICOM.Utilities.1')->GetRandom()
|
|
|
|
|
* 5. openssl_random_pseudo_bytes() (absolute last resort)
|
|
|
|
|
*
|
|
|
|
|
* See RATIONALE.md for our reasoning behind this particular order
|
|
|
|
|
*/
|
|
|
|
|
if (extension_loaded('libsodium')) {
|
|
|
|
|
// See random_bytes_libsodium.php
|
|
|
|
|
if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
|
|
|
|
|
require_once $RandomCompatDIR.'/random_bytes_libsodium.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium.php';
|
|
|
|
|
} elseif (method_exists('Sodium', 'randombytes_buf')) {
|
|
|
|
|
require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium_legacy.php';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -115,7 +117,7 @@ if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
// place, that is not helpful to us here.
|
|
|
|
|
|
|
|
|
|
// See random_bytes_dev_urandom.php
|
|
|
|
|
require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_dev_urandom.php';
|
|
|
|
|
}
|
|
|
|
|
// Unset variables after use
|
|
|
|
|
$RandomCompat_basedir = null;
|
|
|
|
@ -129,7 +131,6 @@ if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
* We only want to use mcypt_create_iv() if:
|
|
|
|
|
*
|
|
|
|
|
* - random_bytes() hasn't already been defined
|
|
|
|
|
* - PHP >= 5.3.7
|
|
|
|
|
* - the mcrypt extensions is loaded
|
|
|
|
|
* - One of these two conditions is true:
|
|
|
|
|
* - We're on Windows (DIRECTORY_SEPARATOR !== '/')
|
|
|
|
@ -139,23 +140,26 @@ if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
* - If we're not on Windows, but the PHP version is between
|
|
|
|
|
* 5.6.10 and 5.6.12, we don't want to use mcrypt. It will
|
|
|
|
|
* hang indefinitely. This is bad.
|
|
|
|
|
* - If we're on Windows, we want to use PHP >= 5.3.7 or else
|
|
|
|
|
* we get insufficient entropy errors.
|
|
|
|
|
*/
|
|
|
|
|
if (
|
|
|
|
|
!is_callable('random_bytes')
|
|
|
|
|
&&
|
|
|
|
|
PHP_VERSION_ID >= 50307
|
|
|
|
|
// Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
|
|
|
|
|
(DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
|
|
|
|
|
&&
|
|
|
|
|
extension_loaded('mcrypt')
|
|
|
|
|
) {
|
|
|
|
|
// Prevent this code from hanging indefinitely on non-Windows;
|
|
|
|
|
// see https://bugs.php.net/bug.php?id=69833
|
|
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
DIRECTORY_SEPARATOR !== '/' ||
|
|
|
|
|
(PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
|
|
|
|
|
)
|
|
|
|
|
&&
|
|
|
|
|
extension_loaded('mcrypt')
|
|
|
|
|
) {
|
|
|
|
|
// See random_bytes_mcrypt.php
|
|
|
|
|
require_once $RandomCompatDIR.'/random_bytes_mcrypt.php';
|
|
|
|
|
}
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_mcrypt.php';
|
|
|
|
|
}
|
|
|
|
|
$RandomCompatUrandom = null;
|
|
|
|
|
|
|
|
|
@ -180,7 +184,7 @@ if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
$RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
|
|
|
|
|
if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
|
|
|
|
|
// See random_bytes_com_dotnet.php
|
|
|
|
|
require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php';
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_com_dotnet.php';
|
|
|
|
|
}
|
|
|
|
|
} catch (com_exception $e) {
|
|
|
|
|
// Don't try to use it.
|
|
|
|
@ -197,19 +201,26 @@ if (PHP_VERSION_ID < 70000) {
|
|
|
|
|
/**
|
|
|
|
|
* We don't have any more options, so let's throw an exception right now
|
|
|
|
|
* and hope the developer won't let it fail silently.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $length
|
|
|
|
|
* @psalm-suppress MissingReturnType
|
|
|
|
|
* @psalm-suppress InvalidReturnType
|
|
|
|
|
* @throws Exception
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
function random_bytes($length)
|
|
|
|
|
{
|
|
|
|
|
unset($length); // Suppress "variable not used" warnings.
|
|
|
|
|
throw new Exception(
|
|
|
|
|
'There is no suitable CSPRNG installed on your system'
|
|
|
|
|
);
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_callable('random_int')) {
|
|
|
|
|
require_once $RandomCompatDIR.'/random_int.php';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$RandomCompatDIR = null;
|
|
|
|
|
if (!is_callable('random_int')) {
|
|
|
|
|
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_int.php';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$RandomCompatDIR = null;
|
|
|
|
|