diff options
Diffstat (limited to 'platform/www/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php')
-rw-r--r-- | platform/www/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/platform/www/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php b/platform/www/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php new file mode 100644 index 0000000..c4e31cc --- /dev/null +++ b/platform/www/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php @@ -0,0 +1,190 @@ +<?php +/** + * Random_* Compatibility Library + * for using the new PHP 7 random_* API in PHP 5 projects + * + * The MIT License (MIT) + * + * 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 + * 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 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +if (!defined('RANDOM_COMPAT_READ_BUFFER')) { + define('RANDOM_COMPAT_READ_BUFFER', 8); +} + +if (!is_callable('random_bytes')) { + /** + * Unless open_basedir is enabled, use /dev/urandom for + * random numbers in accordance with best practices + * + * Why we use /dev/urandom and not /dev/random + * @ref https://www.2uo.de/myths-about-urandom + * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers + * + * @param int $bytes + * + * @throws Exception + * + * @return string + */ + function random_bytes($bytes) + { + /** @var resource $fp */ + static $fp = null; + + /** + * This block should only be run once + */ + if (empty($fp)) { + /** + * We don't want to ever read C:\dev\random, only /dev/urandom on + * Unix-like operating systems. While we guard against this + * condition in random.php, it doesn't hurt to be defensive in depth + * here. + * + * To that end, we only try to open /dev/urandom if we're on a Unix- + * like operating system (which means the directory separator is set + * to "/" not "\". + */ + if (DIRECTORY_SEPARATOR === '/') { + if (!is_readable('/dev/urandom')) { + throw new Exception( + 'Environment misconfiguration: ' . + '/dev/urandom cannot be read.' + ); + } + /** + * We use /dev/urandom if it is a char device. + * We never fall back to /dev/random + */ + /** @var resource|bool $fp */ + $fp = fopen('/dev/urandom', 'rb'); + if (is_resource($fp)) { + /** @var array<string, int> $st */ + $st = fstat($fp); + if (($st['mode'] & 0170000) !== 020000) { + fclose($fp); + $fp = false; + } + } + } + + if (is_resource($fp)) { + /** + * stream_set_read_buffer() does not exist in HHVM + * + * If we don't set the stream's read buffer to 0, PHP will + * internally buffer 8192 bytes, which can waste entropy + * + * stream_set_read_buffer returns 0 on success + */ + if (is_callable('stream_set_read_buffer')) { + stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); + } + if (is_callable('stream_set_chunk_size')) { + stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); + } + } + } + + try { + /** @var int $bytes */ + $bytes = RandomCompat_intval($bytes); + } catch (TypeError $ex) { + throw new TypeError( + '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 + * + * It does not belong in an else {} block, because the above + * if (empty($fp)) line is logic that should only be run once per + * page load. + */ + if (is_resource($fp)) { + /** + * @var int + */ + $remaining = $bytes; + + /** + * @var string|bool + */ + $buf = ''; + + /** + * We use fread() in a loop to protect against partial reads + */ + do { + /** + * @var string|bool + */ + $read = fread($fp, $remaining); + if (!is_string($read)) { + /** + * We cannot safely read from the file. Exit the + * do-while loop and trigger the exception condition + * + * @var string|bool + */ + $buf = false; + break; + } + /** + * Decrease the number of bytes returned from remaining + */ + $remaining -= RandomCompat_strlen($read); + /** + * @var string $buf + */ + $buf .= $read; + } while ($remaining > 0); + + /** + * Is our result valid? + * @var string|bool $buf + */ + if (is_string($buf)) { + if (RandomCompat_strlen($buf) === $bytes) { + /** + * Return our random entropy buffer here: + */ + return $buf; + } + } + } + + /** + * If we reach here, PHP has failed us. + */ + throw new Exception( + 'Error reading from source device' + ); + } +} |