diff options
author | Scott <scott@paragonie.com> | 2016-02-01 07:09:18 -0500 |
---|---|---|
committer | Scott <scott@paragonie.com> | 2016-02-01 07:09:18 -0500 |
commit | 7626d899425ddb5ba6f7bd040b651ccbd0503827 (patch) | |
tree | a39dea60dc66479700589cc875111ab28609bc14 | |
parent | e6f80ab77885151908d0ec743689ca700886e8b0 (diff) | |
parent | e1ddb31788f16f4527074f9f2c1973302eb0cb58 (diff) | |
download | random_compat-7626d899425ddb5ba6f7bd040b651ccbd0503827.zip random_compat-7626d899425ddb5ba6f7bd040b651ccbd0503827.tar.gz random_compat-7626d899425ddb5ba6f7bd040b651ccbd0503827.tar.bz2 |
Merge pull request #88 from voku/master
only ".gitattributes" + whitespace
-rw-r--r-- | .gitattributes | 9 | ||||
-rw-r--r-- | lib/byte_safe_strings.php | 15 | ||||
-rw-r--r-- | lib/cast_to_int.php | 15 | ||||
-rw-r--r-- | lib/random.php | 80 | ||||
-rw-r--r-- | lib/random_bytes_com_dotnet.php | 4 | ||||
-rw-r--r-- | lib/random_bytes_dev_urandom.php | 6 | ||||
-rw-r--r-- | lib/random_bytes_libsodium.php | 2 | ||||
-rw-r--r-- | lib/random_bytes_libsodium_legacy.php | 2 | ||||
-rw-r--r-- | lib/random_bytes_mcrypt.php | 18 | ||||
-rw-r--r-- | lib/random_bytes_openssl.php | 17 | ||||
-rw-r--r-- | lib/random_int.php | 6 |
11 files changed, 130 insertions, 44 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..339e7aa --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +* text=auto + +/tests export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/phpunit.sh export-ignore +/phpunit.xml.dist export-ignore diff --git a/lib/byte_safe_strings.php b/lib/byte_safe_strings.php index a3cc90b..ae3b7b9 100644 --- a/lib/byte_safe_strings.php +++ b/lib/byte_safe_strings.php @@ -50,8 +50,10 @@ if (!function_exists('RandomCompat_strlen')) { 'RandomCompat_strlen() expects a string' ); } + return mb_strlen($binary_string, '8bit'); } + } else { /** * strlen() implementation that isn't brittle to mbstring.func_overload @@ -77,8 +79,10 @@ if (!function_exists('RandomCompat_strlen')) { } if (!function_exists('RandomCompat_substr')) { + if ( - defined('MB_OVERLOAD_STRING') && + defined('MB_OVERLOAD_STRING') + && ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING ) { /** @@ -102,11 +106,13 @@ if (!function_exists('RandomCompat_substr')) { 'RandomCompat_substr(): First argument should be a string' ); } + if (!is_int($start)) { throw new TypeError( 'RandomCompat_substr(): Second argument should be an integer' ); } + if ($length === null) { /** * mb_substr($str, 0, NULL, '8bit') returns an empty string on @@ -118,9 +124,12 @@ if (!function_exists('RandomCompat_substr')) { 'RandomCompat_substr(): Third argument should be an integer, or omitted' ); } + return mb_substr($binary_string, $start, $length, '8bit'); } + } else { + /** * substr() implementation that isn't brittle to mbstring.func_overload * @@ -141,19 +150,23 @@ if (!function_exists('RandomCompat_substr')) { 'RandomCompat_substr(): First argument should be a string' ); } + if (!is_int($start)) { throw new TypeError( 'RandomCompat_substr(): Second argument should be an integer' ); } + if ($length !== null) { if (!is_int($length)) { throw new TypeError( 'RandomCompat_substr(): Third argument should be an integer, or omitted' ); } + return substr($binary_string, $start, $length); } + return substr($binary_string, $start); } } diff --git a/lib/cast_to_int.php b/lib/cast_to_int.php index 474ce64..f441c5d 100644 --- a/lib/cast_to_int.php +++ b/lib/cast_to_int.php @@ -37,26 +37,33 @@ if (!function_exists('RandomCompat_intval')) { * lose precision, so the <= and => operators might accidentally let a float * through. * - * @param numeric $number The number we want to convert to an int - * @param boolean $fail_open Set to true to not throw an exception + * @param int|float $number The number we want to convert to an int + * @param boolean $fail_open Set to true to not throw an exception * * @return int (or float if $fail_open) + * + * @throws TypeError */ function RandomCompat_intval($number, $fail_open = false) { if (is_numeric($number)) { $number += 0; } + if ( - is_float($number) && - $number > ~PHP_INT_MAX && + is_float($number) + && + $number > ~PHP_INT_MAX + && $number < PHP_INT_MAX ) { $number = (int) $number; } + if (is_int($number) || $fail_open) { return $number; } + throw new TypeError( 'Expected an integer.' ); diff --git a/lib/random.php b/lib/random.php index 81ac023..42237ea 100644 --- a/lib/random.php +++ b/lib/random.php @@ -1,22 +1,22 @@ <?php /** - * Random_* Compatibility Library + * Random_* Compatibility Library * for using the new PHP 7 random_* API in PHP 5 projects - * + * * The MIT License (MIT) - * + * * Copyright (c) 2015 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 * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,31 +29,41 @@ if (!defined('PHP_VERSION_ID')) { // This constant was introduced in PHP 5.2.7 $RandomCompatversion = explode('.', PHP_VERSION); - define('PHP_VERSION_ID', ($RandomCompatversion[0] * 10000 + $RandomCompatversion[1] * 100 + $RandomCompatversion[2])); + define( + 'PHP_VERSION_ID', + $RandomCompatversion[0] * 10000 + + $RandomCompatversion[1] * 100 + + $RandomCompatversion[2] + ); $RandomCompatversion = null; } + if (PHP_VERSION_ID < 70000) { + if (!defined('RANDOM_COMPAT_READ_BUFFER')) { define('RANDOM_COMPAT_READ_BUFFER', 8); } + $RandomCompatDIR = dirname(__FILE__); + require_once $RandomCompatDIR.'/byte_safe_strings.php'; require_once $RandomCompatDIR.'/cast_to_int.php'; require_once $RandomCompatDIR.'/error_polyfill.php'; + if (!function_exists('random_bytes')) { /** * PHP 5.2.0 - 5.6.x way to implement random_bytes() - * + * * We use conditional statements here to define the function in accordance * to the operating environment. It's a micro-optimization. - * + * * In order of preference: * 1. Use libsodium if available. * 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 ERRATA.md for our reasoning behind this particular order */ if (extension_loaded('libsodium')) { @@ -64,6 +74,7 @@ if (PHP_VERSION_ID < 70000) { require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php'; } } + /** * Reading directly from /dev/urandom: */ @@ -72,6 +83,7 @@ if (PHP_VERSION_ID < 70000) { // way to exclude Windows. $RandomCompatUrandom = true; $RandomCompat_basedir = ini_get('open_basedir'); + if (!empty($RandomCompat_basedir)) { $RandomCompat_open_basedir = explode( PATH_SEPARATOR, @@ -83,15 +95,18 @@ if (PHP_VERSION_ID < 70000) { ); $RandomCompat_open_basedir = null; } + if ( - !function_exists('random_bytes') && - $RandomCompatUrandom && + !function_exists('random_bytes') + && + $RandomCompatUrandom + && @is_readable('/dev/urandom') ) { // Error suppression on is_readable() in case of an open_basedir // or safe_mode failure. All we care about is whether or not we - // can read it at this point. If the PHP environment is going to - // panic over trying to see if the file can be read in the first + // can read it at this point. If the PHP environment is going to + // panic over trying to see if the file can be read in the first // place, that is not helpful to us here. // See random_bytes_dev_urandom.php @@ -101,28 +116,33 @@ if (PHP_VERSION_ID < 70000) { $RandomCompatUrandom = null; $RandomCompat_basedir = null; } - + /** * mcrypt_create_iv() */ if ( - !function_exists('random_bytes') && - PHP_VERSION_ID >= 50307 && + !function_exists('random_bytes') + && + PHP_VERSION_ID >= 50307 + && extension_loaded('mcrypt') ) { // See random_bytes_mcrypt.php require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; } + if ( - !function_exists('random_bytes') && - extension_loaded('com_dotnet') && + !function_exists('random_bytes') + && + extension_loaded('com_dotnet') + && class_exists('COM') ) { $RandomCompat_disabled_classes = preg_split( - '#\s*,\s*#', + '#\s*,\s*#', strtolower(ini_get('disable_classes')) ); - + if (!in_array('com', $RandomCompat_disabled_classes)) { try { $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); @@ -137,27 +157,31 @@ if (PHP_VERSION_ID < 70000) { $RandomCompat_disabled_classes = null; $RandomCompatCOMtest = null; } - + /** * openssl_random_pseudo_bytes() */ if ( - !function_exists('random_bytes') && - extension_loaded('openssl') && ( // Unix-like with PHP >= 5.3.0 or ( - DIRECTORY_SEPARATOR === '/' && + DIRECTORY_SEPARATOR === '/' + && PHP_VERSION_ID >= 50300 - ) || + ) + || // Windows with PHP >= 5.4.1 PHP_VERSION_ID >= 50401 ) + && + !function_exists('random_bytes') + && + extension_loaded('openssl') ) { // See random_bytes_openssl.php require_once $RandomCompatDIR.'/random_bytes_openssl.php'; } - + /** * throw new Exception */ @@ -174,8 +198,10 @@ if (PHP_VERSION_ID < 70000) { } } } + if (!function_exists('random_int')) { require_once $RandomCompatDIR.'/random_int.php'; } + $RandomCompatDIR = null; } diff --git a/lib/random_bytes_com_dotnet.php b/lib/random_bytes_com_dotnet.php index 0a781f4..3422825 100644 --- a/lib/random_bytes_com_dotnet.php +++ b/lib/random_bytes_com_dotnet.php @@ -46,14 +46,17 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + $buf = ''; $util = new COM('CAPICOM.Utilities.1'); $execCount = 0; + /** * Let's not let it loop forever. If we run N times and fail to * get N bytes of random data, then CAPICOM has failed us. @@ -68,6 +71,7 @@ function random_bytes($bytes) } ++$execCount; } while ($execCount < $bytes); + /** * If we reach here, PHP has failed us. */ diff --git a/lib/random_bytes_dev_urandom.php b/lib/random_bytes_dev_urandom.php index 5d07104..db93b07 100644 --- a/lib/random_bytes_dev_urandom.php +++ b/lib/random_bytes_dev_urandom.php @@ -62,6 +62,7 @@ function random_bytes($bytes) $fp = false; } } + if (!empty($fp)) { /** * stream_set_read_buffer() does not exist in HHVM @@ -79,6 +80,7 @@ function random_bytes($bytes) } } } + try { $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { @@ -86,11 +88,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + /** * This if() block only runs if we managed to open a file handle * @@ -101,6 +105,7 @@ function random_bytes($bytes) if (!empty($fp)) { $remaining = $bytes; $buf = ''; + /** * We use fread() in a loop to protect against partial reads */ @@ -133,6 +138,7 @@ function random_bytes($bytes) } } } + /** * If we reach here, PHP has failed us. */ diff --git a/lib/random_bytes_libsodium.php b/lib/random_bytes_libsodium.php index 938cac9..f802d4e 100644 --- a/lib/random_bytes_libsodium.php +++ b/lib/random_bytes_libsodium.php @@ -48,11 +48,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + /** * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be * generated in one invocation. diff --git a/lib/random_bytes_libsodium_legacy.php b/lib/random_bytes_libsodium_legacy.php index 4c76ff9..44fddbf 100644 --- a/lib/random_bytes_libsodium_legacy.php +++ b/lib/random_bytes_libsodium_legacy.php @@ -48,11 +48,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + /** * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be * generated in one invocation. diff --git a/lib/random_bytes_mcrypt.php b/lib/random_bytes_mcrypt.php index 5a1b688..7ac9d91 100644 --- a/lib/random_bytes_mcrypt.php +++ b/lib/random_bytes_mcrypt.php @@ -48,6 +48,7 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' @@ -55,14 +56,17 @@ function random_bytes($bytes) } $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); - if ($buf !== false) { - if (RandomCompat_strlen($buf) === $bytes) { - /** - * Return our random entropy buffer here: - */ - return $buf; - } + if ( + $buf !== false + && + RandomCompat_strlen($buf) === $bytes + ) { + /** + * Return our random entropy buffer here: + */ + return $buf; } + /** * If we reach here, PHP has failed us. */ diff --git a/lib/random_bytes_openssl.php b/lib/random_bytes_openssl.php index 3e12d3d..62bf770 100644 --- a/lib/random_bytes_openssl.php +++ b/lib/random_bytes_openssl.php @@ -48,12 +48,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } - $secure = true; + /** * $secure is passed by reference. If it's set to false, fail. Note * that this will only return false if this function fails to return @@ -61,12 +62,18 @@ function random_bytes($bytes) * * @ref https://github.com/paragonie/random_compat/issues/6#issuecomment-119564973 */ + $secure = true; $buf = openssl_random_pseudo_bytes($bytes, $secure); - if ($buf !== false && $secure) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } + if ( + $buf !== false + && + $secure + && + RandomCompat_strlen($buf) === $bytes + ) { + return $buf; } + /** * If we reach here, PHP has failed us. */ diff --git a/lib/random_int.php b/lib/random_int.php index 6c91dbc..fd3ef87 100644 --- a/lib/random_int.php +++ b/lib/random_int.php @@ -55,6 +55,7 @@ function random_int($min, $max) 'random_int(): $min must be an integer' ); } + try { $max = RandomCompat_intval($max); } catch (TypeError $ex) { @@ -73,6 +74,7 @@ function random_int($min, $max) 'Minimum value must be less than or equal to the maximum value' ); } + if ($max === $min) { return $min; } @@ -98,6 +100,7 @@ function random_int($min, $max) * Test for integer overflow: */ if (!is_int($range)) { + /** * Still safely calculate wider ranges. * Provided by @CodesInChaos, @oittaa @@ -111,7 +114,9 @@ function random_int($min, $max) */ $bytes = PHP_INT_SIZE; $mask = ~0; + } else { + /** * $bits is effectively ceil(log($range, 2)) without dealing with * type juggling @@ -181,5 +186,6 @@ function random_int($min, $max) * then try again. */ } while (!is_int($val) || $val > $max || $val < $min); + return (int) $val; } |