From 26086981a24e72f283da38dbdb992f27b4135a80 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Tue, 08 Sep 2015 11:38:19 -0400 Subject: [PATCH] Improve randomness of security tokens (#1490529) --- program/lib/Roundcube/rcube_utils.php | 62 ++++++++++++++++++++++++++++--- 1 files changed, 56 insertions(+), 6 deletions(-) diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index 842f677..063296d 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -1090,25 +1090,31 @@ } /** - * Generate a ramdom string + * Generate a random string * * @param int $length String length - * @param bool $raw Return RAW data instead of hex + * @param bool $raw Return RAW data instead of ascii * * @return string The generated random string */ public static function random_bytes($length, $raw = false) { - $rlen = $raw ? $length : ceil($length / 2); - $random = openssl_random_pseudo_bytes($rlen); + // Use PHP7 true random generator + if (function_exists('random_bytes')) { + $random = @random_bytes($length); + } + + if (!$random) { + $random = openssl_random_pseudo_bytes($length); + } if ($raw) { return $random; } - $random = bin2hex($random); + $random = self::bin2ascii($random); - // if the length wasn't even... + // truncate to the specified size... if ($length < strlen($random)) { $random = substr($random, 0, $length); } @@ -1117,6 +1123,50 @@ } /** + * Convert binary data into readable form (containing a-zA-Z0-9 characters) + * + * @param string $input Binary input + * + * @return string Readable output + */ + public static function bin2ascii($input) + { + // Above method returns "hexits". + // Based on bin_to_readable() function in ext/session/session.c. + // Note: removed ",-" characters from hextab + $hextab = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $nbits = 6; // can be 4, 5 or 6 + $length = strlen($input); + $result = ''; + $char = 0; + $i = 0; + $have = 0; + $mask = (1 << $nbits) - 1; + + while (true) { + if ($have < $nbits) { + if ($i < $length) { + $char |= ord($input[$i++]) << $have; + $have += 8; + } + else if (!$have) { + break; + } + else { + $have = $nbits; + } + } + + // consume nbits + $result .= $hextab[$char & $mask]; + $char >>= $nbits; + $have -= $nbits; + } + + return $result; + } + + /** * Format current date according to specified format. * This method supports microseconds (u). * -- Gitblit v1.9.1