Index: t3lib/class.t3lib_div.php =================================================================== --- t3lib/class.t3lib_div.php (Revision 8492) +++ t3lib/class.t3lib_div.php (Arbeitskopie) @@ -1533,42 +1533,64 @@ /** * Returns a string of highly randomized bytes (over the full 8-bit range). + * + * When optional parameter $cryptoSafe is enabled, the function tries to + * retrieve crypto-safe bytes. As this might block the execution for a certain + * time, you should enable it only for crytographic use-cases like encryption. + * + * The function cannot guarantee to return crypto-safe bytes but will at least + * return highly randomized bytes. * * @copyright Drupal CMS * @license GNU General Public License version 2 - * @param integer Number of characters (bytes) to return + * @param integer $count: number of characters (bytes) to return + * @param boolean $cryptoSafe: tries to retrieve crypto-safe bytes * @return string Random Bytes + * @see http://bugs.php.net/bug.php?id=52523 + * @see http://www.php-security.org/2010/05/09/mops-submission-04-generating-unpredictable-session-ids-and-hashes/index.html */ - public static function generateRandomBytes($count) { + public static function generateRandomBytes($count, $cryptoSafe = false) { $output = ''; - // /dev/urandom is available on many *nix systems and is considered - // the best commonly available pseudo-random source. - if (TYPO3_OS != 'WIN' && ($fh = @fopen('/dev/urandom', 'rb'))) { - $output = fread($fh, $count); - fclose($fh); - } elseif (TYPO3_OS == 'WIN') { + + // try to retrieve crypto safe bytes from OpenSSL + if ($cryptoSafe && version_compare(PHP_VERSION, '5.3.0', '>=') + && function_exists('openssl_random_pseudo_bytes')) { + $isStrong = null; + $output = openssl_random_pseudo_bytes($count, $isStrong); + // reset random byte string since OpenSSL wasn't using a strong algo + if ($isStrong !== TRUE) { + $output = ''; + } + } + + // try to retrieve crypto safe bytes from Windows COM API + if ($cryptoSafe && $output === '' && TYPO3_OS == 'WIN') { if (class_exists('COM')) { try { $com = new COM('CAPICOM.Utilities.1'); $output = base64_decode($com->GetRandom($count, 0)); } catch(Exception $e) { - // CAPICOM not installed + // CAPICOM not installed/registered } } - if ($output === '' && version_compare(PHP_VERSION, '5.3.0', '>=')) { - if (function_exists('mcrypt_create_iv')) { - $output = mcrypt_create_iv($count, MCRYPT_DEV_URANDOM); - } elseif (function_exists('openssl_random_pseudo_bytes')) { - $isStrong = null; - $output = openssl_random_pseudo_bytes($count, $isStrong); - // skip ssl since it wasn't using the strong algo - if ($isStrong !== TRUE) { - $output = ''; - } - } - } } + + // try to retrieve non-crypto safe bytes (pseudo-random source) on *nix systems + if ($output === '' && TYPO3_OS != 'WIN' && is_readable('/dev/urandom') + && ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } + // try to retrieve non-crypto safe bytes (pseudo-random source) on windows systems + if ($output === '' && TYPO3_OS == 'WIN' && version_compare(PHP_VERSION, '5.3.0', '>=') + && function_exists('mcrypt_create_iv')) { + $iv = mcrypt_create_iv($count, MCRYPT_DEV_URANDOM); + // reset random byte string in case of a mcrypt error + $output = ($iv !== false ? $iv : ''); + } + + // fallback if other random byte generation failed until now if (!isset($output{$count - 1})) { // We initialize with the somewhat random.