A WordPress-centric search engine for devs and theme authors



random_bytes ›

Sincen/a
Deprecatedn/a
random_bytes ( $bytes )
Parameters:
  • (int) $bytes
    Required: Yes
Returns:
  • (string)
Defined at:
Codex:

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



Source

function random_bytes($bytes)
    {
        static $fp = null;
        /**
         * This block should only be run once
         */
        if (empty($fp)) {
            /**
             * We use /dev/urandom if it is a char device.
             * We never fall back to /dev/random
             */
            $fp = fopen('/dev/urandom', 'rb');
            if (!empty($fp)) {
                $st = fstat($fp);
                if (($st['mode'] & 0170000) !== 020000) {
                    fclose($fp);
                    $fp = false;
                }
            }

            if (!empty($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 {
            $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 (!empty($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)) {
                    if ($read === false) {
                        /**
                         * 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|bool
                 */
                $buf = $buf . $read;
            } while ($remaining > 0);

            /**
             * Is our result valid?
             */
            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'
        );
    }
}