X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Flibs%2FCryptRand.php;h=f7702dd3ac54121048ee8d12aeaef54dd081cdf0;hb=f9ad69d2a5312b0565a5b1a3762aa812f6b5cfb9;hp=6d18c81ed608140edaca085133e342c44080066c;hpb=531ed101ccd14dc7e2cf2858a67b2523ef6a79ff;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/libs/CryptRand.php b/includes/libs/CryptRand.php index 6d18c81ed6..f7702dd3ac 100644 --- a/includes/libs/CryptRand.php +++ b/includes/libs/CryptRand.php @@ -94,9 +94,9 @@ class CryptRand { $files[] = dirname( __DIR__ ); foreach ( $files as $file ) { - MediaWiki\suppressWarnings(); + Wikimedia\suppressWarnings(); $stat = stat( $file ); - MediaWiki\restoreWarnings(); + Wikimedia\restoreWarnings(); if ( $stat ) { // stat() duplicates data into numeric and string keys so kill off all the numeric ones foreach ( $stat as $k => $v ) { @@ -182,7 +182,7 @@ class CryptRand { $this->logger->debug( "Clock drift calculation " . "(time-taken=" . ( $timeTaken * 1000 ) . "ms, " . "iterations=$iterations, " . - "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)\n" ); + "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)" ); return $data; } @@ -234,9 +234,6 @@ class CryptRand { * @return string Raw binary random data */ public function generate( $bytes, $forceStrong = false ) { - - $this->logger->debug( "Generating cryptographic random bytes for\n" ); - $bytes = floor( $bytes ); static $buffer = ''; if ( is_null( $this->strong ) ) { @@ -245,42 +242,57 @@ class CryptRand { } if ( strlen( $buffer ) < $bytes ) { + // If available make use of PHP 7's random_bytes + // On Linux, getrandom syscall will be used if available. + // On Windows CryptGenRandom will always be used + // On other platforms, /dev/urandom will be used. + // Avoids polyfills from before php 7.0 + // All error situations will throw Exceptions and or Errors + if ( PHP_VERSION_ID >= 70000 + || ( defined( 'HHVM_VERSION_ID' ) && HHVM_VERSION_ID >= 31101 ) + ) { + $rem = $bytes - strlen( $buffer ); + $buffer .= random_bytes( $rem ); + } + if ( strlen( $buffer ) >= $bytes ) { + $this->strong = true; + } + } + + if ( strlen( $buffer ) < $bytes && function_exists( 'mcrypt_create_iv' ) ) { // If available make use of mcrypt_create_iv URANDOM source to generate randomness // On unix-like systems this reads from /dev/urandom but does it without any buffering // and bypasses openbasedir restrictions, so it's preferable to reading directly // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate // entropy so this is also preferable to just trying to read urandom because it may work // on Windows systems as well. - if ( function_exists( 'mcrypt_create_iv' ) ) { - $rem = $bytes - strlen( $buffer ); - $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM ); - if ( $iv === false ) { - $this->logger->debug( "mcrypt_create_iv returned false.\n" ); - } else { - $buffer .= $iv; - $this->logger->debug( "mcrypt_create_iv generated " . strlen( $iv ) . - " bytes of randomness.\n" ); - } + $rem = $bytes - strlen( $buffer ); + $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM ); + if ( $iv === false ) { + $this->logger->debug( "mcrypt_create_iv returned false." ); + } else { + $buffer .= $iv; + $this->logger->debug( "mcrypt_create_iv generated " . strlen( $iv ) . + " bytes of randomness." ); } } - if ( strlen( $buffer ) < $bytes ) { - if ( function_exists( 'openssl_random_pseudo_bytes' ) ) { - $rem = $bytes - strlen( $buffer ); - $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong ); - if ( $openssl_bytes === false ) { - $this->logger->debug( "openssl_random_pseudo_bytes returned false.\n" ); - } else { - $buffer .= $openssl_bytes; - $this->logger->debug( "openssl_random_pseudo_bytes generated " . - strlen( $openssl_bytes ) . " bytes of " . - ( $openssl_strong ? "strong" : "weak" ) . " randomness.\n" ); - } - if ( strlen( $buffer ) >= $bytes ) { - // openssl tells us if the random source was strong, if some of our data was generated - // using it use it's say on whether the randomness is strong - $this->strong = !!$openssl_strong; - } + if ( strlen( $buffer ) < $bytes && function_exists( 'openssl_random_pseudo_bytes' ) ) { + $rem = $bytes - strlen( $buffer ); + $openssl_strong = false; + $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong ); + if ( $openssl_bytes === false ) { + $this->logger->debug( "openssl_random_pseudo_bytes returned false." ); + } else { + $buffer .= $openssl_bytes; + $this->logger->debug( "openssl_random_pseudo_bytes generated " . + strlen( $openssl_bytes ) . " bytes of " . + ( $openssl_strong ? "strong" : "weak" ) . " randomness." ); + } + if ( strlen( $buffer ) >= $bytes ) { + // openssl tells us if the random source was strong, if some of our data was generated + // using it use it's say on whether the randomness is strong + $this->strong = !!$openssl_strong; } } @@ -291,13 +303,13 @@ class CryptRand { $rem = $bytes - strlen( $buffer ); if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) { $this->logger->debug( "Was forced to read from /dev/urandom " . - "without control over the buffer size.\n" ); + "without control over the buffer size." ); } // /dev/urandom is generally considered the best possible commonly // available random source, and is available on most *nix systems. - MediaWiki\suppressWarnings(); + Wikimedia\suppressWarnings(); $urandom = fopen( "/dev/urandom", "rb" ); - MediaWiki\restoreWarnings(); + Wikimedia\restoreWarnings(); // Attempt to read all our random data from urandom // php's fread always does buffered reads based on the stream's chunk_size @@ -317,14 +329,14 @@ class CryptRand { $buffer .= $random_bytes; fclose( $urandom ); $this->logger->debug( "/dev/urandom generated " . strlen( $random_bytes ) . - " bytes of randomness.\n" ); + " bytes of randomness." ); if ( strlen( $buffer ) >= $bytes ) { // urandom is always strong, set to true if all our data was generated using it $this->strong = true; } } else { - $this->logger->debug( "/dev/urandom could not be opened.\n" ); + $this->logger->debug( "/dev/urandom could not be opened." ); } } @@ -336,7 +348,7 @@ class CryptRand { // out and being used to predict the /randomness/ that follows. if ( strlen( $buffer ) < $bytes ) { $this->logger->debug( __METHOD__ . - ": Falling back to using a pseudo random state to generate randomness.\n" ); + ": Falling back to using a pseudo random state to generate randomness." ); } while ( strlen( $buffer ) < $bytes ) { $buffer .= MWCryptHash::hmac( $this->randomState(), strval( mt_rand() ) ); @@ -352,7 +364,7 @@ class CryptRand { $buffer = substr( $buffer, $bytes ); $this->logger->debug( strlen( $buffer ) . - " bytes of randomness leftover in the buffer.\n" ); + " bytes of randomness leftover in the buffer." ); return $generated; }