Changeset 42130
- Timestamp:
- 11/08/2017 11:47:04 AM (7 years ago)
- Location:
- trunk/src/wp-includes/random_compat
- Files:
-
- 1 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/random_compat/byte_safe_strings.php
r36886 r42130 6 6 * The MIT License (MIT) 7 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 27 27 */ 28 28 29 if (! function_exists('RandomCompat_strlen')) {29 if (!is_callable('RandomCompat_strlen')) { 30 30 if ( 31 31 defined('MB_OVERLOAD_STRING') && … … 52 52 } 53 53 54 return mb_strlen($binary_string, '8bit');54 return (int) mb_strlen($binary_string, '8bit'); 55 55 } 56 56 … … 74 74 ); 75 75 } 76 return strlen($binary_string);76 return (int) strlen($binary_string); 77 77 } 78 78 } 79 79 } 80 80 81 if (! function_exists('RandomCompat_substr')) {81 if (!is_callable('RandomCompat_substr')) { 82 82 83 83 if ( … … 119 119 * PHP 5.3, so we have to find the length ourselves. 120 120 */ 121 $length = RandomCompat_strlen($ length) - $start;121 $length = RandomCompat_strlen($binary_string) - $start; 122 122 } elseif (!is_int($length)) { 123 123 throw new TypeError( … … 126 126 } 127 127 128 return mb_substr($binary_string, $start, $length, '8bit'); 128 // Consistency with PHP's behavior 129 if ($start === RandomCompat_strlen($binary_string) && $length === 0) { 130 return ''; 131 } 132 if ($start > RandomCompat_strlen($binary_string)) { 133 return ''; 134 } 135 136 return (string) mb_substr($binary_string, $start, $length, '8bit'); 129 137 } 130 138 … … 165 173 } 166 174 167 return substr($binary_string, $start, $length);175 return (string) substr($binary_string, $start, $length); 168 176 } 169 177 170 return substr($binary_string, $start);178 return (string) substr($binary_string, $start); 171 179 } 172 180 } -
trunk/src/wp-includes/random_compat/cast_to_int.php
r36886 r42130 6 6 * The MIT License (MIT) 7 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 27 27 */ 28 28 29 if (! function_exists('RandomCompat_intval')) {29 if (!is_callable('RandomCompat_intval')) { 30 30 31 31 /** … … 39 39 * 40 40 * @param int|float $number The number we want to convert to an int 41 * @param bool ean$fail_open Set to true to not throw an exception41 * @param bool $fail_open Set to true to not throw an exception 42 42 * 43 * @return int (or float if $fail_open) 43 * @return float|int 44 * @psalm-suppress InvalidReturnType 44 45 * 45 46 * @throws TypeError … … 47 48 function RandomCompat_intval($number, $fail_open = false) 48 49 { 49 if (is_numeric($number)) { 50 if (is_int($number) || is_float($number)) { 51 $number += 0; 52 } elseif (is_numeric($number)) { 50 53 $number += 0; 51 54 } … … 61 64 } 62 65 63 if (is_int($number) || $fail_open) { 64 return $number; 66 if (is_int($number)) { 67 return (int) $number; 68 } elseif (!$fail_open) { 69 throw new TypeError( 70 'Expected an integer.' 71 ); 65 72 } 66 67 throw new TypeError( 68 'Expected an integer.' 69 ); 73 return $number; 70 74 } 71 75 } -
trunk/src/wp-includes/random_compat/error_polyfill.php
r35365 r42130 5 5 * 6 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises7 * 8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 36 36 37 37 if (!class_exists('TypeError', false)) { 38 class TypeError extends Error 39 { 40 38 if (is_subclass_of('Error', 'Exception')) { 39 class TypeError extends Error 40 { 41 42 } 43 } else { 44 class TypeError extends Exception 45 { 46 47 } 41 48 } 42 49 } -
trunk/src/wp-includes/random_compat/random.php
r36886 r42130 4 4 * for using the new PHP 7 random_* API in PHP 5 projects 5 5 * 6 * @version 1.2.17 * @released 201 6-02-296 * @version 2.0.10 7 * @released 2017-03-13 8 8 * 9 9 * The MIT License (MIT) 10 10 * 11 * Copyright (c) 2015 Paragon Initiative Enterprises11 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 12 12 * 13 13 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 32 32 if (!defined('PHP_VERSION_ID')) { 33 33 // This constant was introduced in PHP 5.2.7 34 $RandomCompatversion = explode('.', PHP_VERSION);34 $RandomCompatversion = array_map('intval', explode('.', PHP_VERSION)); 35 35 define( 36 36 'PHP_VERSION_ID', … … 42 42 } 43 43 44 if (PHP_VERSION_ID < 70000) { 45 46 if (!defined('RANDOM_COMPAT_READ_BUFFER')) { 47 define('RANDOM_COMPAT_READ_BUFFER', 8); 48 } 49 50 $RandomCompatDIR = dirname(__FILE__); 51 52 require_once $RandomCompatDIR.'/byte_safe_strings.php'; 53 require_once $RandomCompatDIR.'/cast_to_int.php'; 54 require_once $RandomCompatDIR.'/error_polyfill.php'; 55 56 if (!function_exists('random_bytes')) { 44 /** 45 * PHP 7.0.0 and newer have these functions natively. 46 */ 47 if (PHP_VERSION_ID >= 70000) { 48 return; 49 } 50 51 if (!defined('RANDOM_COMPAT_READ_BUFFER')) { 52 define('RANDOM_COMPAT_READ_BUFFER', 8); 53 } 54 55 $RandomCompatDIR = dirname(__FILE__); 56 57 require_once $RandomCompatDIR . '/byte_safe_strings.php'; 58 require_once $RandomCompatDIR . '/cast_to_int.php'; 59 require_once $RandomCompatDIR . '/error_polyfill.php'; 60 61 if (!is_callable('random_bytes')) { 62 /** 63 * PHP 5.2.0 - 5.6.x way to implement random_bytes() 64 * 65 * We use conditional statements here to define the function in accordance 66 * to the operating environment. It's a micro-optimization. 67 * 68 * In order of preference: 69 * 1. Use libsodium if available. 70 * 2. fread() /dev/urandom if available (never on Windows) 71 * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM) 72 * 4. COM('CAPICOM.Utilities.1')->GetRandom() 73 * 74 * See RATIONALE.md for our reasoning behind this particular order 75 */ 76 if (extension_loaded('libsodium')) { 77 // See random_bytes_libsodium.php 78 if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) { 79 require_once $RandomCompatDIR . '/random_bytes_libsodium.php'; 80 } elseif (method_exists('Sodium', 'randombytes_buf')) { 81 require_once $RandomCompatDIR . '/random_bytes_libsodium_legacy.php'; 82 } 83 } 84 85 /** 86 * Reading directly from /dev/urandom: 87 */ 88 if (DIRECTORY_SEPARATOR === '/') { 89 // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast 90 // way to exclude Windows. 91 $RandomCompatUrandom = true; 92 $RandomCompat_basedir = ini_get('open_basedir'); 93 94 if (!empty($RandomCompat_basedir)) { 95 $RandomCompat_open_basedir = explode( 96 PATH_SEPARATOR, 97 strtolower($RandomCompat_basedir) 98 ); 99 $RandomCompatUrandom = (array() !== array_intersect( 100 array('/dev', '/dev/', '/dev/urandom'), 101 $RandomCompat_open_basedir 102 )); 103 $RandomCompat_open_basedir = null; 104 } 105 106 if ( 107 !is_callable('random_bytes') 108 && 109 $RandomCompatUrandom 110 && 111 @is_readable('/dev/urandom') 112 ) { 113 // Error suppression on is_readable() in case of an open_basedir 114 // or safe_mode failure. All we care about is whether or not we 115 // can read it at this point. If the PHP environment is going to 116 // panic over trying to see if the file can be read in the first 117 // place, that is not helpful to us here. 118 119 // See random_bytes_dev_urandom.php 120 require_once $RandomCompatDIR . '/random_bytes_dev_urandom.php'; 121 } 122 // Unset variables after use 123 $RandomCompat_basedir = null; 124 } else { 125 $RandomCompatUrandom = false; 126 } 127 128 /** 129 * mcrypt_create_iv() 130 * 131 * We only want to use mcypt_create_iv() if: 132 * 133 * - random_bytes() hasn't already been defined 134 * - the mcrypt extensions is loaded 135 * - One of these two conditions is true: 136 * - We're on Windows (DIRECTORY_SEPARATOR !== '/') 137 * - We're not on Windows and /dev/urandom is readabale 138 * (i.e. we're not in a chroot jail) 139 * - Special case: 140 * - If we're not on Windows, but the PHP version is between 141 * 5.6.10 and 5.6.12, we don't want to use mcrypt. It will 142 * hang indefinitely. This is bad. 143 * - If we're on Windows, we want to use PHP >= 5.3.7 or else 144 * we get insufficient entropy errors. 145 */ 146 if ( 147 !is_callable('random_bytes') 148 && 149 // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be. 150 (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307) 151 && 152 // Prevent this code from hanging indefinitely on non-Windows; 153 // see https://bugs.php.net/bug.php?id=69833 154 ( 155 DIRECTORY_SEPARATOR !== '/' || 156 (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) 157 ) 158 && 159 extension_loaded('mcrypt') 160 ) { 161 // See random_bytes_mcrypt.php 162 require_once $RandomCompatDIR . '/random_bytes_mcrypt.php'; 163 } 164 $RandomCompatUrandom = null; 165 166 /** 167 * This is a Windows-specific fallback, for when the mcrypt extension 168 * isn't loaded. 169 */ 170 if ( 171 !is_callable('random_bytes') 172 && 173 extension_loaded('com_dotnet') 174 && 175 class_exists('COM') 176 ) { 177 $RandomCompat_disabled_classes = preg_split( 178 '#\s*,\s*#', 179 strtolower(ini_get('disable_classes')) 180 ); 181 182 if (!in_array('com', $RandomCompat_disabled_classes)) { 183 try { 184 $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); 185 if (method_exists($RandomCompatCOMtest, 'GetRandom')) { 186 // See random_bytes_com_dotnet.php 187 require_once $RandomCompatDIR . '/random_bytes_com_dotnet.php'; 188 } 189 } catch (com_exception $e) { 190 // Don't try to use it. 191 } 192 } 193 $RandomCompat_disabled_classes = null; 194 $RandomCompatCOMtest = null; 195 } 196 197 /** 198 * throw new Exception 199 */ 200 if (!is_callable('random_bytes')) { 57 201 /** 58 * PHP 5.2.0 - 5.6.x way to implement random_bytes() 202 * We don't have any more options, so let's throw an exception right now 203 * and hope the developer won't let it fail silently. 59 204 * 60 * We use conditional statements here to define the function in accordance 61 * to the operating environment. It's a micro-optimization. 62 * 63 * In order of preference: 64 * 1. Use libsodium if available. 65 * 2. fread() /dev/urandom if available (never on Windows) 66 * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM) 67 * 4. COM('CAPICOM.Utilities.1')->GetRandom() 68 * 5. openssl_random_pseudo_bytes() (absolute last resort) 69 * 70 * See ERRATA.md for our reasoning behind this particular order 205 * @param mixed $length 206 * @return void 207 * @throws Exception 71 208 */ 72 if (extension_loaded('libsodium')) { 73 // See random_bytes_libsodium.php 74 if (PHP_VERSION_ID >= 50300 && function_exists('\\Sodium\\randombytes_buf')) { 75 require_once $RandomCompatDIR.'/random_bytes_libsodium.php'; 76 } elseif (method_exists('Sodium', 'randombytes_buf')) { 77 require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php'; 78 } 79 } 80 81 /** 82 * Reading directly from /dev/urandom: 83 */ 84 if (DIRECTORY_SEPARATOR === '/') { 85 // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast 86 // way to exclude Windows. 87 $RandomCompatUrandom = true; 88 $RandomCompat_basedir = ini_get('open_basedir'); 89 90 if (!empty($RandomCompat_basedir)) { 91 $RandomCompat_open_basedir = explode( 92 PATH_SEPARATOR, 93 strtolower($RandomCompat_basedir) 94 ); 95 $RandomCompatUrandom = in_array( 96 '/dev', 97 $RandomCompat_open_basedir 98 ); 99 $RandomCompat_open_basedir = null; 100 } 101 102 if ( 103 !function_exists('random_bytes') 104 && 105 $RandomCompatUrandom 106 && 107 @is_readable('/dev/urandom') 108 ) { 109 // Error suppression on is_readable() in case of an open_basedir 110 // or safe_mode failure. All we care about is whether or not we 111 // can read it at this point. If the PHP environment is going to 112 // panic over trying to see if the file can be read in the first 113 // place, that is not helpful to us here. 114 115 // See random_bytes_dev_urandom.php 116 require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php'; 117 } 118 // Unset variables after use 119 $RandomCompat_basedir = null; 120 $RandomCompatUrandom = null; 121 } 122 123 /** 124 * mcrypt_create_iv() 125 */ 126 if ( 127 !function_exists('random_bytes') 128 && 129 PHP_VERSION_ID >= 50307 130 && 131 extension_loaded('mcrypt') 132 ) { 133 // Prevent this code from hanging indefinitely on non-Windows; 134 // see https://bugs.php.net/bug.php?id=69833 135 if ( 136 DIRECTORY_SEPARATOR !== '/' || 137 (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) 138 ) { 139 // See random_bytes_mcrypt.php 140 require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; 141 } 142 } 143 144 if ( 145 !function_exists('random_bytes') 146 && 147 extension_loaded('com_dotnet') 148 && 149 class_exists('COM') 150 ) { 151 $RandomCompat_disabled_classes = preg_split( 152 '#\s*,\s*#', 153 strtolower(ini_get('disable_classes')) 209 function random_bytes($length) 210 { 211 unset($length); // Suppress "variable not used" warnings. 212 throw new Exception( 213 'There is no suitable CSPRNG installed on your system' 154 214 ); 155 156 if (!in_array('com', $RandomCompat_disabled_classes)) { 157 try { 158 $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); 159 if (method_exists($RandomCompatCOMtest, 'GetRandom')) { 160 // See random_bytes_com_dotnet.php 161 require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php'; 162 } 163 } catch (com_exception $e) { 164 // Don't try to use it. 165 } 166 } 167 $RandomCompat_disabled_classes = null; 168 $RandomCompatCOMtest = null; 169 } 170 171 /** 172 * openssl_random_pseudo_bytes() 173 */ 174 if ( 175 ( 176 // Unix-like with PHP >= 5.3.0 or 177 ( 178 DIRECTORY_SEPARATOR === '/' 179 && 180 PHP_VERSION_ID >= 50300 181 ) 182 || 183 // Windows with PHP >= 5.4.1 184 PHP_VERSION_ID >= 50401 185 ) 186 && 187 !function_exists('random_bytes') 188 && 189 extension_loaded('openssl') 190 ) { 191 // See random_bytes_openssl.php 192 require_once $RandomCompatDIR.'/random_bytes_openssl.php'; 193 } 194 195 /** 196 * throw new Exception 197 */ 198 if (!function_exists('random_bytes')) { 199 /** 200 * We don't have any more options, so let's throw an exception right now 201 * and hope the developer won't let it fail silently. 202 */ 203 function random_bytes($length) 204 { 205 throw new Exception( 206 'There is no suitable CSPRNG installed on your system' 207 ); 208 } 209 } 210 } 211 212 if (!function_exists('random_int')) { 213 require_once $RandomCompatDIR.'/random_int.php'; 214 } 215 216 $RandomCompatDIR = null; 217 } 215 } 216 } 217 } 218 219 if (!is_callable('random_int')) { 220 require_once $RandomCompatDIR . '/random_int.php'; 221 } 222 223 $RandomCompatDIR = null; -
trunk/src/wp-includes/random_compat/random_bytes_com_dotnet.php
r36886 r42130 6 6 * The MIT License (MIT) 7 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 27 27 */ 28 28 29 /** 30 * Windows with PHP < 5.3.0 will not have the function 31 * openssl_random_pseudo_bytes() available, so let's use 32 * CAPICOM to work around this deficiency. 33 * 34 * @param int $bytes 35 * 36 * @throws Exception 37 * 38 * @return string 39 */ 40 function random_bytes($bytes) 41 { 42 try { 43 $bytes = RandomCompat_intval($bytes); 44 } catch (TypeError $ex) { 45 throw new TypeError( 46 'random_bytes(): $bytes must be an integer' 29 if (!is_callable('random_bytes')) { 30 /** 31 * Windows with PHP < 5.3.0 will not have the function 32 * openssl_random_pseudo_bytes() available, so let's use 33 * CAPICOM to work around this deficiency. 34 * 35 * @param int $bytes 36 * 37 * @throws Exception 38 * 39 * @return string 40 */ 41 function random_bytes($bytes) 42 { 43 try { 44 $bytes = RandomCompat_intval($bytes); 45 } catch (TypeError $ex) { 46 throw new TypeError( 47 'random_bytes(): $bytes must be an integer' 48 ); 49 } 50 51 if ($bytes < 1) { 52 throw new Error( 53 'Length must be greater than 0' 54 ); 55 } 56 57 $buf = ''; 58 if (!class_exists('COM')) { 59 throw new Error( 60 'COM does not exist' 61 ); 62 } 63 $util = new COM('CAPICOM.Utilities.1'); 64 $execCount = 0; 65 66 /** 67 * Let's not let it loop forever. If we run N times and fail to 68 * get N bytes of random data, then CAPICOM has failed us. 69 */ 70 do { 71 $buf .= base64_decode($util->GetRandom($bytes, 0)); 72 if (RandomCompat_strlen($buf) >= $bytes) { 73 /** 74 * Return our random entropy buffer here: 75 */ 76 return RandomCompat_substr($buf, 0, $bytes); 77 } 78 ++$execCount; 79 } while ($execCount < $bytes); 80 81 /** 82 * If we reach here, PHP has failed us. 83 */ 84 throw new Exception( 85 'Could not gather sufficient random data' 47 86 ); 48 87 } 49 50 if ($bytes < 1) {51 throw new Error(52 'Length must be greater than 0'53 );54 }55 56 $buf = '';57 $util = new COM('CAPICOM.Utilities.1');58 $execCount = 0;59 60 /**61 * Let's not let it loop forever. If we run N times and fail to62 * get N bytes of random data, then CAPICOM has failed us.63 */64 do {65 $buf .= base64_decode($util->GetRandom($bytes, 0));66 if (RandomCompat_strlen($buf) >= $bytes) {67 /**68 * Return our random entropy buffer here:69 */70 return RandomCompat_substr($buf, 0, $bytes);71 }72 ++$execCount;73 } while ($execCount < $bytes);74 75 /**76 * If we reach here, PHP has failed us.77 */78 throw new Exception(79 'Could not gather sufficient random data'80 );81 88 } -
trunk/src/wp-includes/random_compat/random_bytes_dev_urandom.php
r36886 r42130 5 5 * 6 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises7 * 8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 31 31 } 32 32 33 /** 34 * Unless open_basedir is enabled, use /dev/urandom for 35 * random numbers in accordance with best practices 36 * 37 * Why we use /dev/urandom and not /dev/random 38 * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers 39 * 40 * @param int $bytes 41 * 42 * @throws Exception 43 * 44 * @return string 45 */ 46 function random_bytes($bytes) 47 { 48 static $fp = null; 33 if (!is_callable('random_bytes')) { 49 34 /** 50 * This block should only be run once 35 * Unless open_basedir is enabled, use /dev/urandom for 36 * random numbers in accordance with best practices 37 * 38 * Why we use /dev/urandom and not /dev/random 39 * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers 40 * 41 * @param int $bytes 42 * 43 * @throws Exception 44 * 45 * @return string 51 46 */ 52 if (empty($fp)) { 47 function random_bytes($bytes) 48 { 49 static $fp = null; 53 50 /** 54 * We use /dev/urandom if it is a char device. 55 * We never fall back to /dev/random 51 * This block should only be run once 56 52 */ 57 $fp = fopen('/dev/urandom', 'rb'); 58 if (!empty($fp)) { 59 $st = fstat($fp); 60 if (($st['mode'] & 0170000) !== 020000) { 61 fclose($fp); 62 $fp = false; 53 if (empty($fp)) { 54 /** 55 * We use /dev/urandom if it is a char device. 56 * We never fall back to /dev/random 57 */ 58 $fp = fopen('/dev/urandom', 'rb'); 59 if (!empty($fp)) { 60 $st = fstat($fp); 61 if (($st['mode'] & 0170000) !== 020000) { 62 fclose($fp); 63 $fp = false; 64 } 65 } 66 67 if (!empty($fp)) { 68 /** 69 * stream_set_read_buffer() does not exist in HHVM 70 * 71 * If we don't set the stream's read buffer to 0, PHP will 72 * internally buffer 8192 bytes, which can waste entropy 73 * 74 * stream_set_read_buffer returns 0 on success 75 */ 76 if (is_callable('stream_set_read_buffer')) { 77 stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); 78 } 79 if (is_callable('stream_set_chunk_size')) { 80 stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); 81 } 63 82 } 64 83 } 65 84 85 try { 86 $bytes = RandomCompat_intval($bytes); 87 } catch (TypeError $ex) { 88 throw new TypeError( 89 'random_bytes(): $bytes must be an integer' 90 ); 91 } 92 93 if ($bytes < 1) { 94 throw new Error( 95 'Length must be greater than 0' 96 ); 97 } 98 99 /** 100 * This if() block only runs if we managed to open a file handle 101 * 102 * It does not belong in an else {} block, because the above 103 * if (empty($fp)) line is logic that should only be run once per 104 * page load. 105 */ 66 106 if (!empty($fp)) { 67 107 /** 68 * stream_set_read_buffer() does not exist in HHVM 69 * 70 * If we don't set the stream's read buffer to 0, PHP will 71 * internally buffer 8192 bytes, which can waste entropy 72 * 73 * stream_set_read_buffer returns 0 on success 108 * @var int 74 109 */ 75 if (function_exists('stream_set_read_buffer')) { 76 stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); 77 } 78 if (function_exists('stream_set_chunk_size')) { 79 stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); 110 $remaining = $bytes; 111 112 /** 113 * @var string|bool 114 */ 115 $buf = ''; 116 117 /** 118 * We use fread() in a loop to protect against partial reads 119 */ 120 do { 121 /** 122 * @var string|bool 123 */ 124 $read = fread($fp, $remaining); 125 if (!is_string($read)) { 126 if ($read === false) { 127 /** 128 * We cannot safely read from the file. Exit the 129 * do-while loop and trigger the exception condition 130 * 131 * @var string|bool 132 */ 133 $buf = false; 134 break; 135 } 136 } 137 /** 138 * Decrease the number of bytes returned from remaining 139 */ 140 $remaining -= RandomCompat_strlen($read); 141 /** 142 * @var string|bool 143 */ 144 $buf = $buf . $read; 145 } while ($remaining > 0); 146 147 /** 148 * Is our result valid? 149 */ 150 if (is_string($buf)) { 151 if (RandomCompat_strlen($buf) === $bytes) { 152 /** 153 * Return our random entropy buffer here: 154 */ 155 return $buf; 156 } 80 157 } 81 158 } 82 }83 159 84 try {85 $bytes = RandomCompat_intval($bytes);86 } catch (TypeError $ex) {87 throw new TypeError(88 ' random_bytes(): $bytes must be an integer'160 /** 161 * If we reach here, PHP has failed us. 162 */ 163 throw new Exception( 164 'Error reading from source device' 89 165 ); 90 166 } 91 92 if ($bytes < 1) {93 throw new Error(94 'Length must be greater than 0'95 );96 }97 98 /**99 * This if() block only runs if we managed to open a file handle100 *101 * It does not belong in an else {} block, because the above102 * if (empty($fp)) line is logic that should only be run once per103 * page load.104 */105 if (!empty($fp)) {106 $remaining = $bytes;107 $buf = '';108 109 /**110 * We use fread() in a loop to protect against partial reads111 */112 do {113 $read = fread($fp, $remaining);114 if ($read === false) {115 /**116 * We cannot safely read from the file. Exit the117 * do-while loop and trigger the exception condition118 */119 $buf = false;120 break;121 }122 /**123 * Decrease the number of bytes returned from remaining124 */125 $remaining -= RandomCompat_strlen($read);126 $buf .= $read;127 } while ($remaining > 0);128 129 /**130 * Is our result valid?131 */132 if ($buf !== false) {133 if (RandomCompat_strlen($buf) === $bytes) {134 /**135 * Return our random entropy buffer here:136 */137 return $buf;138 }139 }140 }141 142 /**143 * If we reach here, PHP has failed us.144 */145 throw new Exception(146 'Error reading from source device'147 );148 167 } -
trunk/src/wp-includes/random_compat/random_bytes_libsodium.php
r36886 r42130 5 5 * 6 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises7 * 8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 27 27 */ 28 28 29 /** 30 * If the libsodium PHP extension is loaded, we'll use it above any other 31 * solution. 32 * 33 * libsodium-php project: 34 * @ref https://github.com/jedisct1/libsodium-php 35 * 36 * @param int $bytes 37 * 38 * @throws Exception 39 * 40 * @return string 41 */ 42 function random_bytes($bytes) 43 { 44 try { 45 $bytes = RandomCompat_intval($bytes); 46 } catch (TypeError $ex) { 47 throw new TypeError( 48 'random_bytes(): $bytes must be an integer' 29 if (!is_callable('random_bytes')) { 30 /** 31 * If the libsodium PHP extension is loaded, we'll use it above any other 32 * solution. 33 * 34 * libsodium-php project: 35 * @ref https://github.com/jedisct1/libsodium-php 36 * 37 * @param int $bytes 38 * 39 * @throws Exception 40 * 41 * @return string 42 */ 43 function random_bytes($bytes) 44 { 45 try { 46 $bytes = RandomCompat_intval($bytes); 47 } catch (TypeError $ex) { 48 throw new TypeError( 49 'random_bytes(): $bytes must be an integer' 50 ); 51 } 52 53 if ($bytes < 1) { 54 throw new Error( 55 'Length must be greater than 0' 56 ); 57 } 58 59 /** 60 * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be 61 * generated in one invocation. 62 */ 63 if ($bytes > 2147483647) { 64 $buf = ''; 65 for ($i = 0; $i < $bytes; $i += 1073741824) { 66 $n = ($bytes - $i) > 1073741824 67 ? 1073741824 68 : $bytes - $i; 69 $buf .= \Sodium\randombytes_buf($n); 70 } 71 } else { 72 $buf = \Sodium\randombytes_buf($bytes); 73 } 74 75 if ($buf !== false) { 76 if (RandomCompat_strlen($buf) === $bytes) { 77 return $buf; 78 } 79 } 80 81 /** 82 * If we reach here, PHP has failed us. 83 */ 84 throw new Exception( 85 'Could not gather sufficient random data' 49 86 ); 50 87 } 51 52 if ($bytes < 1) {53 throw new Error(54 'Length must be greater than 0'55 );56 }57 58 /**59 * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be60 * generated in one invocation.61 */62 if ($bytes > 2147483647) {63 $buf = '';64 for ($i = 0; $i < $bytes; $i += 1073741824) {65 $n = ($bytes - $i) > 107374182466 ? 107374182467 : $bytes - $i;68 $buf .= \Sodium\randombytes_buf($n);69 }70 } else {71 $buf = \Sodium\randombytes_buf($bytes);72 }73 74 if ($buf !== false) {75 if (RandomCompat_strlen($buf) === $bytes) {76 return $buf;77 }78 }79 80 /**81 * If we reach here, PHP has failed us.82 */83 throw new Exception(84 'Could not gather sufficient random data'85 );86 88 } -
trunk/src/wp-includes/random_compat/random_bytes_libsodium_legacy.php
r36886 r42130 5 5 * 6 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises7 * 8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 27 27 */ 28 28 29 /** 30 * If the libsodium PHP extension is loaded, we'll use it above any other 31 * solution. 32 * 33 * libsodium-php project: 34 * @ref https://github.com/jedisct1/libsodium-php 35 * 36 * @param int $bytes 37 * 38 * @throws Exception 39 * 40 * @return string 41 */ 42 function random_bytes($bytes) 43 { 44 try { 45 $bytes = RandomCompat_intval($bytes); 46 } catch (TypeError $ex) { 47 throw new TypeError( 48 'random_bytes(): $bytes must be an integer' 29 if (!is_callable('random_bytes')) { 30 /** 31 * If the libsodium PHP extension is loaded, we'll use it above any other 32 * solution. 33 * 34 * libsodium-php project: 35 * @ref https://github.com/jedisct1/libsodium-php 36 * 37 * @param int $bytes 38 * 39 * @throws Exception 40 * 41 * @return string 42 */ 43 function random_bytes($bytes) 44 { 45 try { 46 $bytes = RandomCompat_intval($bytes); 47 } catch (TypeError $ex) { 48 throw new TypeError( 49 'random_bytes(): $bytes must be an integer' 50 ); 51 } 52 53 if ($bytes < 1) { 54 throw new Error( 55 'Length must be greater than 0' 56 ); 57 } 58 59 /** 60 * @var string 61 */ 62 $buf = ''; 63 64 /** 65 * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be 66 * generated in one invocation. 67 */ 68 if ($bytes > 2147483647) { 69 for ($i = 0; $i < $bytes; $i += 1073741824) { 70 $n = ($bytes - $i) > 1073741824 71 ? 1073741824 72 : $bytes - $i; 73 $buf .= Sodium::randombytes_buf((int) $n); 74 } 75 } else { 76 $buf .= Sodium::randombytes_buf((int) $bytes); 77 } 78 79 if (is_string($buf)) { 80 if (RandomCompat_strlen($buf) === $bytes) { 81 return $buf; 82 } 83 } 84 85 /** 86 * If we reach here, PHP has failed us. 87 */ 88 throw new Exception( 89 'Could not gather sufficient random data' 49 90 ); 50 91 } 51 52 if ($bytes < 1) {53 throw new Error(54 'Length must be greater than 0'55 );56 }57 58 /**59 * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be60 * generated in one invocation.61 */62 if ($bytes > 2147483647) {63 $buf = '';64 for ($i = 0; $i < $bytes; $i += 1073741824) {65 $n = ($bytes - $i) > 107374182466 ? 107374182467 : $bytes - $i;68 $buf .= Sodium::randombytes_buf($n);69 }70 } else {71 $buf = Sodium::randombytes_buf($bytes);72 }73 74 if ($buf !== false) {75 if (RandomCompat_strlen($buf) === $bytes) {76 return $buf;77 }78 }79 80 /**81 * If we reach here, PHP has failed us.82 */83 throw new Exception(84 'Could not gather sufficient random data'85 );86 92 } -
trunk/src/wp-includes/random_compat/random_bytes_mcrypt.php
r36886 r42130 5 5 * 6 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2015 Paragon Initiative Enterprises7 * 8 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 9 9 * 10 10 * Permission is hereby granted, free of charge, to any person obtaining a copy … … 27 27 */ 28 28 29 if (!is_callable('random_bytes')) { 30 /** 31 * Powered by ext/mcrypt (and thankfully NOT libmcrypt) 32 * 33 * @ref https://bugs.php.net/bug.php?id=55169 34 * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386 35 * 36 * @param int $bytes 37 * 38 * @throws Exception 39 * 40 * @return string 41 */ 42 function random_bytes($bytes) 43 { 44 try { 45 $bytes = RandomCompat_intval($bytes); 46 } catch (TypeError $ex) { 47 throw new TypeError( 48 'random_bytes(): $bytes must be an integer' 49 ); 50 } 29 51 30 /** 31 * Powered by ext/mcrypt (and thankfully NOT libmcrypt) 32 * 33 * @ref https://bugs.php.net/bug.php?id=55169 34 * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386 35 * 36 * @param int $bytes 37 * 38 * @throws Exception 39 * 40 * @return string 41 */ 42 function random_bytes($bytes) 43 { 44 try { 45 $bytes = RandomCompat_intval($bytes); 46 } catch (TypeError $ex) { 47 throw new TypeError( 48 'random_bytes(): $bytes must be an integer' 52 if ($bytes < 1) { 53 throw new Error( 54 'Length must be greater than 0' 55 ); 56 } 57 58 $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); 59 if ( 60 $buf !== false 61 && 62 RandomCompat_strlen($buf) === $bytes 63 ) { 64 /** 65 * Return our random entropy buffer here: 66 */ 67 return $buf; 68 } 69 70 /** 71 * If we reach here, PHP has failed us. 72 */ 73 throw new Exception( 74 'Could not gather sufficient random data' 49 75 ); 50 76 } 51 52 if ($bytes < 1) {53 throw new Error(54 'Length must be greater than 0'55 );56 }57 58 $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);59 if (60 $buf !== false61 &&62 RandomCompat_strlen($buf) === $bytes63 ) {64 /**65 * Return our random entropy buffer here:66 */67 return $buf;68 }69 70 /**71 * If we reach here, PHP has failed us.72 */73 throw new Exception(74 'Could not gather sufficient random data'75 );76 77 } -
trunk/src/wp-includes/random_compat/random_int.php
r36886 r42130 1 1 <?php 2 /**3 * Random_* Compatibility Library4 * for using the new PHP 7 random_* API in PHP 5 projects5 *6 * The MIT License (MIT)7 *8 * Copyright (c) 2015 Paragon Initiative Enterprises9 *10 * Permission is hereby granted, free of charge, to any person obtaining a copy11 * of this software and associated documentation files (the "Software"), to deal12 * in the Software without restriction, including without limitation the rights13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell14 * copies of the Software, and to permit persons to whom the Software is15 * furnished to do so, subject to the following conditions:16 *17 * The above copyright notice and this permission notice shall be included in18 * all copies or substantial portions of the Software.19 *20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE26 * SOFTWARE.27 */28 2 29 /** 30 * Fetch a random integer between $min and $max inclusive 31 * 32 * @param int $min 33 * @param int $max 34 * 35 * @throws Exception 36 * 37 * @return int 38 */ 39 function random_int($min, $max) 40 { 3 if (!is_callable('random_int')) { 41 4 /** 42 * Type and input logic checks 43 * 44 * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) 45 * (non-inclusive), it will sanely cast it to an int. If you it's equal to 46 * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats 47 * lose precision, so the <= and => operators might accidentally let a float 48 * through. 5 * Random_* Compatibility Library 6 * for using the new PHP 7 random_* API in PHP 5 projects 7 * 8 * The MIT License (MIT) 9 * 10 * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a copy 13 * of this software and associated documentation files (the "Software"), to deal 14 * in the Software without restriction, including without limitation the rights 15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 * copies of the Software, and to permit persons to whom the Software is 17 * furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included in 20 * all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 * SOFTWARE. 49 29 */ 50 51 try {52 $min = RandomCompat_intval($min);53 } catch (TypeError $ex) {54 throw new TypeError(55 'random_int(): $min must be an integer'56 );57 }58 59 try {60 $max = RandomCompat_intval($max);61 } catch (TypeError $ex) {62 throw new TypeError(63 'random_int(): $max must be an integer'64 );65 }66 67 /**68 * Now that we've verified our weak typing system has given us an integer,69 * let's validate the logic then we can move forward with generating random70 * integers along a given range.71 */72 if ($min > $max) {73 throw new Error(74 'Minimum value must be less than or equal to the maximum value'75 );76 }77 78 if ($max === $min) {79 return $min;80 }81 30 82 31 /** 83 * Initialize variables to 0 84 * 85 * We want to store: 86 * $bytes => the number of random bytes we need 87 * $mask => an integer bitmask (for use with the &) operator 88 * so we can minimize the number of discards 32 * Fetch a random integer between $min and $max inclusive 33 * 34 * @param int $min 35 * @param int $max 36 * 37 * @throws Exception 38 * 39 * @return int 89 40 */ 90 $attempts = $bits = $bytes = $mask = $valueShift = 0; 41 function random_int($min, $max) 42 { 43 /** 44 * Type and input logic checks 45 * 46 * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) 47 * (non-inclusive), it will sanely cast it to an int. If you it's equal to 48 * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats 49 * lose precision, so the <= and => operators might accidentally let a float 50 * through. 51 */ 91 52 92 /** 93 * At this point, $range is a positive number greater than 0. It might 94 * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to 95 * a float and we will lose some precision. 96 */ 97 $range = $max - $min; 53 try { 54 $min = RandomCompat_intval($min); 55 } catch (TypeError $ex) { 56 throw new TypeError( 57 'random_int(): $min must be an integer' 58 ); 59 } 98 60 99 /** 100 * Test for integer overflow: 101 */ 102 if (!is_int($range)) { 103 104 /** 105 * Still safely calculate wider ranges. 106 * Provided by @CodesInChaos, @oittaa 107 * 108 * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 109 * 110 * We use ~0 as a mask in this case because it generates all 1s 111 * 112 * @ref https://eval.in/400356 (32-bit) 113 * @ref http://3v4l.org/XX9r5 (64-bit) 114 */ 115 $bytes = PHP_INT_SIZE; 116 $mask = ~0; 117 118 } else { 119 120 /** 121 * $bits is effectively ceil(log($range, 2)) without dealing with 122 * type juggling 123 */ 124 while ($range > 0) { 125 if ($bits % 8 === 0) { 126 ++$bytes; 127 } 128 ++$bits; 129 $range >>= 1; 130 $mask = $mask << 1 | 1; 131 } 132 $valueShift = $min; 133 } 134 135 /** 136 * Now that we have our parameters set up, let's begin generating 137 * random integers until one falls between $min and $max 138 */ 139 do { 140 /** 141 * The rejection probability is at most 0.5, so this corresponds 142 * to a failure probability of 2^-128 for a working RNG 143 */ 144 if ($attempts > 128) { 145 throw new Exception( 146 'random_int: RNG is broken - too many rejections' 61 try { 62 $max = RandomCompat_intval($max); 63 } catch (TypeError $ex) { 64 throw new TypeError( 65 'random_int(): $max must be an integer' 147 66 ); 148 67 } 149 68 150 69 /** 151 * Let's grab the necessary number of random bytes 70 * Now that we've verified our weak typing system has given us an integer, 71 * let's validate the logic then we can move forward with generating random 72 * integers along a given range. 152 73 */ 153 $randomByteString = random_bytes($bytes); 154 if ($randomByteString === false) { 155 throw new Exception( 156 'Random number generator failure' 74 if ($min > $max) { 75 throw new Error( 76 'Minimum value must be less than or equal to the maximum value' 157 77 ); 158 78 } 159 79 160 /** 161 * Let's turn $randomByteString into an integer 162 * 163 * This uses bitwise operators (<< and |) to build an integer 164 * out of the values extracted from ord() 165 * 166 * Example: [9F] | [6D] | [32] | [0C] => 167 * 159 + 27904 + 3276800 + 201326592 => 168 * 204631455 169 */ 170 $val = 0; 171 for ($i = 0; $i < $bytes; ++$i) { 172 $val |= ord($randomByteString[$i]) << ($i * 8); 80 if ($max === $min) { 81 return (int) $min; 173 82 } 174 83 175 84 /** 176 * Apply mask 85 * Initialize variables to 0 86 * 87 * We want to store: 88 * $bytes => the number of random bytes we need 89 * $mask => an integer bitmask (for use with the &) operator 90 * so we can minimize the number of discards 177 91 */ 178 $val &= $mask; 179 $val += $valueShift; 92 $attempts = $bits = $bytes = $mask = $valueShift = 0; 180 93 181 ++$attempts;182 94 /** 183 * If $val overflows to a floating point number, 184 * ... or is larger than $max, 185 * ... or smaller than $min, 186 * then try again. 95 * At this point, $range is a positive number greater than 0. It might 96 * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to 97 * a float and we will lose some precision. 187 98 */ 188 } while (!is_int($val) || $val > $max || $val < $min);99 $range = $max - $min; 189 100 190 return (int) $val; 101 /** 102 * Test for integer overflow: 103 */ 104 if (!is_int($range)) { 105 106 /** 107 * Still safely calculate wider ranges. 108 * Provided by @CodesInChaos, @oittaa 109 * 110 * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 111 * 112 * We use ~0 as a mask in this case because it generates all 1s 113 * 114 * @ref https://eval.in/400356 (32-bit) 115 * @ref http://3v4l.org/XX9r5 (64-bit) 116 */ 117 $bytes = PHP_INT_SIZE; 118 $mask = ~0; 119 120 } else { 121 122 /** 123 * $bits is effectively ceil(log($range, 2)) without dealing with 124 * type juggling 125 */ 126 while ($range > 0) { 127 if ($bits % 8 === 0) { 128 ++$bytes; 129 } 130 ++$bits; 131 $range >>= 1; 132 $mask = $mask << 1 | 1; 133 } 134 $valueShift = $min; 135 } 136 137 $val = 0; 138 /** 139 * Now that we have our parameters set up, let's begin generating 140 * random integers until one falls between $min and $max 141 */ 142 do { 143 /** 144 * The rejection probability is at most 0.5, so this corresponds 145 * to a failure probability of 2^-128 for a working RNG 146 */ 147 if ($attempts > 128) { 148 throw new Exception( 149 'random_int: RNG is broken - too many rejections' 150 ); 151 } 152 153 /** 154 * Let's grab the necessary number of random bytes 155 */ 156 $randomByteString = random_bytes($bytes); 157 158 /** 159 * Let's turn $randomByteString into an integer 160 * 161 * This uses bitwise operators (<< and |) to build an integer 162 * out of the values extracted from ord() 163 * 164 * Example: [9F] | [6D] | [32] | [0C] => 165 * 159 + 27904 + 3276800 + 201326592 => 166 * 204631455 167 */ 168 $val &= 0; 169 for ($i = 0; $i < $bytes; ++$i) { 170 $val |= ord($randomByteString[$i]) << ($i * 8); 171 } 172 173 /** 174 * Apply mask 175 */ 176 $val &= $mask; 177 $val += $valueShift; 178 179 ++$attempts; 180 /** 181 * If $val overflows to a floating point number, 182 * ... or is larger than $max, 183 * ... or smaller than $min, 184 * then try again. 185 */ 186 } while (!is_int($val) || $val > $max || $val < $min); 187 188 return (int) $val; 189 } 191 190 }
Note: See TracChangeset
for help on using the changeset viewer.