diff --git a/src/filesystem/Filesystem.php b/src/filesystem/Filesystem.php --- a/src/filesystem/Filesystem.php +++ b/src/filesystem/Filesystem.php @@ -421,6 +421,13 @@ throw new Exception(pht('You must generate at least 1 byte of entropy.')); } + // Under PHP 7.2.0 and newer, we have a reasonable builtin. For older + // versions, we fall back to various sources which have a roughly similar + // effect. + if (function_exists('random_bytes')) { + return random_bytes($number_of_bytes); + } + // Try to use `openssl_random_pseudo_bytes()` if it's available. This source // is the most widely available source, and works on Windows/Linux/OSX/etc. @@ -530,6 +537,30 @@ } + /** + * Generate a random integer value in a given range. + * + * This method uses less-entropic random sources under older versions of PHP. + * + * @param int Minimum value, inclusive. + * @param int Maximum value, inclusive. + */ + public static function readRandomInteger($min, $max) { + // Under PHP 7.2.0 and newer, we can just use "random_int()". This function + // is intended to generate cryptographically usable entropy. + if (function_exists('random_int')) { + return random_int($min, $max); + } + + // We could find a stronger source for this, but correctly converting raw + // bytes to an integer range without biases is fairly hard and it seems + // like we're more likely to get that wrong than suffer a PRNG prediction + // issue by falling back to "mt_rand()". + + return mt_rand($min, $max); + } + + /** * Identify the MIME type of a file. This returns only the MIME type (like * text/plain), not the encoding (like charset=utf-8).