PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / extra / hub-connector / lib / PHPSecLib / Crypt / Random.php

Random.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at extra/hub-connector/lib/PHPSecLib/Crypt/Random.php

345 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Random Number Generator
5 *
6 * The idea behind this function is that it can be easily replaced with your own crypt_random_string()
7 * function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
8 *
9 * PHP versions 4 and 5
10 *
11 * Here's a short example of how to use this library:
12 * <code>
13 * <?php
14 * include 'Crypt/Random.php';
15 *
16 * echo bin2hex(crypt_random_string(8));
17 * ?>
18 * </code>
19 *
20 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
21 * of this software and associated documentation files (the "Software"), to deal
22 * in the Software without restriction, including without limitation the rights
23 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 * copies of the Software, and to permit persons to whom the Software is
25 * furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice shall be included in
28 * all copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 * THE SOFTWARE.
37 *
38 * @category Crypt
39 * @package Crypt_Random
40 * @author Jim Wigginton <[email protected]>
41 * @copyright 2007 Jim Wigginton
42 * @license http://www.opensource.org/licenses/mit-license.html MIT License
43 * @link http://phpseclib.sourceforge.net
44 */
45
46 // laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
47 // have phpseclib as a requirement as well. if you're developing such a program you may encounter
48 // a "Cannot redeclare crypt_random_string()" error.
49 if (!function_exists('crypt_random_string')) {
50 /**
51 * "Is Windows" test
52 *
53 * @access private
54 */
55 define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
56
57 /**
58 * Generate a random string.
59 *
60 * Although microoptimizations are generally discouraged as they impair readability this function is ripe with
61 * microoptimizations because this function has the potential of being called a huge number of times.
62 * eg. for RSA key generation.
63 *
64 * @param int $length
65 * @return string
66 * @access public
67 */
68 function crypt_random_string($length)
69 {
70 if (!$length) {
71 return '';
72 }
73
74 if (CRYPT_RANDOM_IS_WINDOWS) {
75 // method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows
76 if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
77 return @mcrypt_create_iv($length);
78 }
79 // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
80 // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
81 // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
82 // call php_win32_get_random_bytes():
83 //
84 // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
85 // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
86 //
87 // php_win32_get_random_bytes() is defined thusly:
88 //
89 // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
90 //
91 // we're calling it, all the same, in the off chance that the mcrypt extension is not available
92 if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
93 return openssl_random_pseudo_bytes($length);
94 }
95 } else {
96 // method 1. the fastest
97 if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
98 return openssl_random_pseudo_bytes($length);
99 }
100 // method 2
101 static $fp = true;
102 if ($fp === true) {
103 // warning's will be output unles the error suppression operator is used. errors such as
104 // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
105 $fp = @fopen('/dev/urandom', 'rb');
106 }
107 if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
108 $temp = fread($fp, $length);
109 if (strlen($temp) == $length) {
110 return $temp;
111 }
112 }
113 // method 3. pretty much does the same thing as method 2 per the following url:
114 // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
115 // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
116 // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
117 // restrictions or some such
118 if (extension_loaded('mcrypt')) {
119 return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
120 }
121 }
122 // at this point we have no choice but to use a pure-PHP CSPRNG
123
124 // cascade entropy across multiple PHP instances by fixing the session and collecting all
125 // environmental variables, including the previous session data and the current session
126 // data.
127 //
128 // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
129 // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
130 // PHP isn't low level to be able to use those as sources and on a web server there's not likely
131 // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
132 // however, a ton of people visiting the website. obviously you don't want to base your seeding
133 // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
134 // by the user and (2) this isn't just looking at the data sent by the current user - it's based
135 // on the data sent by all users. one user requests the page and a hash of their info is saved.
136 // another user visits the page and the serialization of their data is utilized along with the
137 // server envirnment stuff and a hash of the previous http request data (which itself utilizes
138 // a hash of the session data before that). certainly an attacker should be assumed to have
139 // full control over his own http requests. he, however, is not going to have control over
140 // everyone's http requests.
141 static $crypto = false, $v;
142 if ($crypto === false) {
143 // save old session data
144 $old_session_id = session_id();
145 $old_use_cookies = ini_get('session.use_cookies');
146 $old_session_cache_limiter = session_cache_limiter();
147 $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
148 if ($old_session_id != '') {
149 session_write_close();
150 }
151
152 session_id(1);
153 ini_set('session.use_cookies', 0);
154 session_cache_limiter('');
155 session_start();
156
157 $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
158 (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
159 (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
160 (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
161 (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
162 // as of PHP 8.1 $GLOBALS can't be accessed by reference, which eliminates
163 // the need for phpseclib_safe_serialize. see https://wiki.php.net/rfc/restrict_globals_usage
164 // for more info
165 (version_compare(PHP_VERSION, '8.1.0', '>=') ? serialize($GLOBALS) : phpseclib_safe_serialize($GLOBALS)) .
166 phpseclib_safe_serialize($_SESSION) .
167 phpseclib_safe_serialize($_OLD_SESSION)
168 ));
169 if (!isset($_SESSION['count'])) {
170 $_SESSION['count'] = 0;
171 }
172 $_SESSION['count']++;
173
174 session_write_close();
175
176 // restore old session data
177 if ($old_session_id != '') {
178 session_id($old_session_id);
179 session_start();
180 ini_set('session.use_cookies', $old_use_cookies);
181 session_cache_limiter($old_session_cache_limiter);
182 } else {
183 if ($_OLD_SESSION !== false) {
184 $_SESSION = $_OLD_SESSION;
185 unset($_OLD_SESSION);
186 } else {
187 unset($_SESSION);
188 }
189 }
190
191 // in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
192 // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
193 // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
194 // original hash and the current hash. we'll be emulating that. for more info see the following URL:
195 //
196 // http://tools.ietf.org/html/rfc4253#section-7.2
197 //
198 // see the is_string($crypto) part for an example of how to expand the keys
199 $key = pack('H*', sha1($seed . 'A'));
200 $iv = pack('H*', sha1($seed . 'C'));
201
202 // ciphers are used as per the nist.gov link below. also, see this link:
203 //
204 // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
205 switch (true) {
206 case phpseclib_resolve_include_path('Crypt/AES.php'):
207 if (!class_exists('Crypt_AES')) {
208 require_once dirname(__FILE__).'/AES.php';
209 }
210 $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
211 break;
212 case phpseclib_resolve_include_path('Crypt/Twofish.php'):
213 if (!class_exists('Crypt_Twofish')) {
214 require_once dirname(__FILE__).'/Twofish.php';
215 }
216 $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
217 break;
218 case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
219 if (!class_exists('Crypt_Blowfish')) {
220 require_once dirname(__FILE__).'/Blowfish.php';
221 }
222 $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
223 break;
224 case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
225 if (!class_exists('Crypt_TripleDES')) {
226 require_once dirname(__FILE__).'/TripleDES.php';
227 }
228 $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
229 break;
230 case phpseclib_resolve_include_path('Crypt/DES.php'):
231 if (!class_exists('Crypt_DES')) {
232 require_once dirname(__FILE__).'/DES.php';
233 }
234 $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
235 break;
236 case phpseclib_resolve_include_path('Crypt/RC4.php'):
237 if (!class_exists('Crypt_RC4')) {
238 require_once dirname(__FILE__).'/RC4.php';
239 }
240 $crypto = new Crypt_RC4();
241 break;
242 default:
243 user_error('crypt_random_string requires at least one symmetric cipher be loaded');
244 return false;
245 }
246
247 $crypto->setKey($key);
248 $crypto->setIV($iv);
249 $crypto->enableContinuousBuffer();
250 }
251
252 //return $crypto->encrypt(str_repeat("\0", $length));
253
254 // the following is based off of ANSI X9.31:
255 //
256 // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
257 //
258 // OpenSSL uses that same standard for it's random numbers:
259 //
260 // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
261 // (do a search for "ANS X9.31 A.2.4")
262 $result = '';
263 while (strlen($result) < $length) {
264 $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
265 $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
266 $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
267 $result.= $r;
268 }
269 return substr($result, 0, $length);
270 }
271 }
272
273 if (!function_exists('phpseclib_safe_serialize')) {
274 /**
275 * Safely serialize variables
276 *
277 * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
278 * PHP 5.3 will emit a warning.
279 *
280 * @param mixed $arr
281 * @access public
282 */
283 function phpseclib_safe_serialize(&$arr)
284 {
285 if (is_object($arr)) {
286 return '';
287 }
288 if (!is_array($arr)) {
289 return serialize($arr);
290 }
291 // prevent circular array recursion
292 if (isset($arr['__phpseclib_marker'])) {
293 return '';
294 }
295 $safearr = array();
296 $arr['__phpseclib_marker'] = true;
297 foreach (array_keys($arr) as $key) {
298 // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
299 if ($key !== '__phpseclib_marker') {
300 $safearr[$key] = phpseclib_safe_serialize($arr[$key]);
301 }
302 }
303 unset($arr['__phpseclib_marker']);
304 return serialize($safearr);
305 }
306 }
307
308 if (!function_exists('phpseclib_resolve_include_path')) {
309 /**
310 * Resolve filename against the include path.
311 *
312 * Wrapper around stream_resolve_include_path() (which was introduced in
313 * PHP 5.3.2) with fallback implementation for earlier PHP versions.
314 *
315 * @param string $filename
316 * @return string|false
317 * @access public
318 */
319 function phpseclib_resolve_include_path($filename)
320 {
321 if (function_exists('stream_resolve_include_path')) {
322 return stream_resolve_include_path($filename);
323 }
324
325 // handle non-relative paths
326 if (file_exists($filename)) {
327 return realpath($filename);
328 }
329
330 $paths = PATH_SEPARATOR == ':' ?
331 preg_split('#(?<!phar):#', get_include_path()) :
332 explode(PATH_SEPARATOR, get_include_path());
333 foreach ($paths as $prefix) {
334 // path's specified in include_path don't always end in /
335 $ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
336 $file = $prefix . $ds . $filename;
337 if (file_exists($file)) {
338 return realpath($file);
339 }
340 }
341
342 return false;
343 }
344 }
345