null]; $options += $defaults; $source = static::$_source ?: (static::$_source = static::_source()); $result = $source($bytes); if ($options['encode'] !== static::ENCODE_BASE_64) { return $result; } return strtr(rtrim(base64_encode($result), '='), '+', '.'); } /** * Returns the best available random number generator source. * * The source of randomness used are as follows: * * 1. `random_bytes()`, available in PHP >=7.0 * 2. `random_bytes()`, available if the openssl extension is installed * 3. `mcrypt_create_iv()`, available if the mcrypt extensions is installed * 4. `/dev/urandom`, available on *nix * 5. `GetRandom()` through COM, available on Windows * * Note: Users restricting path access through the `open_basedir` INI setting, * will need to include `/dev/urandom` into the list of allowed paths, as this * method might read from it. * * @link http://php.net/random_bytes * @link http://php.net/mcrypt_create_iv * @link http://msdn.microsoft.com/en-us/library/aa388182%28VS.85%29.aspx?ppud=4 * @link http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ * @see lithium\util\Random::$_source * @return callable Returns a closure containing a random number generator. */ protected static function _source() { if (function_exists('random_bytes')) { return function($bytes) { return random_bytes($bytes); }; } if (function_exists('openssl_random_pseudo_bytes')) { return function($bytes) { return openssl_random_pseudo_bytes($bytes); }; } if (function_exists('mcrypt_create_iv')) { return function($bytes) { return mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); }; } if (is_readable('/dev/urandom')) { return function($bytes) { $stream = fopen('/dev/urandom', 'rb'); $result = fread($stream, $bytes); fclose($stream); return $result; }; } if (class_exists('COM', false)) { $com = new COM('CAPICOM.Utilities.1'); return function($bytes) use ($com) { return base64_decode($com->GetRandom($bytes, 0)); }; } throw new LogicException('No suitable strong random number generator source found.'); } } ?>