public function filter($value) { //source: http://www.php-security.org/2010/05/09/mops-submission-04-generating-unpredictable-session-ids-and-hashes/ $entropy = ''; // try ssl first if (function_exists('openssl_random_pseudo_bytes')) { $entropy = openssl_random_pseudo_bytes(64, $strong); // skip ssl since it wasn't using the strong algo if ($strong !== true) { $entropy = ''; } } // add some basic mt_rand/uniqid combo $entropy .= uniqid(mt_rand(), true); // try to read from the windows RNG if (class_exists('COM')) { try { $com = new COM('CAPICOM.Utilities.1'); $entropy .= base64_decode($com->GetRandom(64, 0)); } catch (Exception $ex) { } } // try to read from the unix RNG if (is_readable('/dev/urandom')) { $h = fopen('/dev/urandom', 'rb'); $entropy .= fread($h, 64); fclose($h); } $hash = hash('whirlpool', $entropy); return substr($hash, 0, $this->_length); }
function generateUniqueId($maxLength = null) { $entropy = ''; // On test ssl d'abord. if (function_exists('openssl_random_pseudo_bytes')) { $entropy = openssl_random_pseudo_bytes(64, $strong); // skip ssl since it wasn't using the strong algo if ($strong !== true) { $entropy = ''; } } // On ajoute les basics mt_rand/uniqid combo $entropy .= uniqid(mt_rand(), true); // On test la lecture de la fenêtre RNG if (class_exists('COM')) { try { $com = new COM('CAPICOM.Utilities.1'); $entropy .= base64_decode($com->GetRandom(64, 0)); } catch (Exception $ex) { } } // on test la lecture de unix RNG if (is_readable('/dev/urandom')) { $h = fopen('/dev/urandom', 'rb'); $entropy .= fread($h, 64); fclose($h); } $hash = hash('whirlpool', $entropy); if ($maxLength) { return substr($hash, 0, $maxLength); } return $hash; }
public static function generate($maxLength = null) { $entropy = ''; // try ssl first if (function_exists('openssl_random_pseudo_bytes')) { $entropy = openssl_random_pseudo_bytes(64, $strong); // skip ssl since it wasn't using the strong algo if ($strong !== true) { $entropy = ''; } } // add some basic mt_rand/uniqid combo $entropy .= uniqid(mt_rand(), true); // try to read from the windows RNG if (class_exists('COM')) { try { $com = new COM('CAPICOM.Utilities.1'); $entropy .= base64_decode($com->GetRandom(64, 0)); } catch (Exception $ex) { } } // try to read from the unix RNG if (is_readable('/dev/urandom')) { $h = fopen('/dev/urandom', 'rb'); $entropy .= fread($h, 64); fclose($h); } $hash = hash('whirlpool', $entropy); if ($maxLength) { return substr($hash, 0, $maxLength); } return $hash; }
function getRandomBytes($count) { $output = ''; // we will try to obtain entropy from several sources, starting with OpenSSL if (function_exists('openssl_random_pseudo_bytes')) { $strong = FALSE; $output = openssl_random_pseudo_bytes($count, $strong); // if OpenSSL didn't use a strong cryptographic primitive, we'll find another source of entropy if (FALSE == $strong) { $output = ''; } } // if we've got a POSIX system, hopefully urandom is available if ($fd = @fopen('/dev/urandom', 'rb')) { $output = fread($fd, $count); fclose($fd); } // if we're on Windows, hopefully we can use its PRNG if (class_exists('COM')) { @($com = new COM('CAPICOM.Utilities.1')); @($output .= base64_decode($com->GetRandom($count, 0))); } // we fall back to a rather cryptographically insufficient but workable source of entropy if (strlen($output) < $count) { $output = ''; for ($i = 0; $i < $count; $i += 16) { $this->randomState = md5(microtime() . $this->randomState); $output .= md5($this->randomState, TRUE); } $output = substr($output, 0, $count); } return $output; }
/** * Windows with PHP < 5.3.0 will not have the function * openssl_random_pseudo_bytes() available, so let's use * CAPICOM to work around this deficiency. * * @param int $bytes * * @throws Exception * * @return string */ function random_bytes($bytes) { if (!is_int($bytes)) { throw new TypeError('Length must be an integer'); } if ($bytes < 1) { throw new Error('Length must be greater than 0'); } $buf = ''; $util = new COM('CAPICOM.Utilities.1'); $execCount = 0; /** * Let's not let it loop forever. If we run N times and fail to * get N bytes of random data, then CAPICOM has failed us. */ do { $buf .= base64_decode($util->GetRandom($bytes, 0)); if (RandomCompat_strlen($buf) >= $bytes) { /** * Return our random entropy buffer here: */ return RandomCompat_substr($buf, 0, $bytes); } ++$execCount; } while ($execCount < $bytes); /** * If we reach here, PHP has failed us. */ throw new Exception('PHP failed to generate random data.'); }
function zen_get_entropy($seed) { $entropy = ''; $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== FALSE) { $entropy .= @fread($fp, 16); // echo "USING /dev/random" . "<br>"; @fclose($fp); } // MS-Windows platform? if (@class_exists('COM')) { // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $entropy .= $CAPI_Util->GetRandom(16, 0); if ($entropy) { $entropy = md5($entropy, TRUE); // echo "USING WINDOWS" . "<br>"; } } catch (Exception $ex) { // echo 'Exception: ' . $ex->getMessage(); } } if (strlen($entropy) < 16) { $entropy = sha1_file('/includes/configure.php'); $entropy .= microtime() . mt_rand() . $seed; // echo "USING FALLBACK" . "<br>"; } return sha1($entropy); }
/** * Generate a random string of the specified size * * @param int $size The size of the requested random string * * @return string A string of the requested size */ public function generate($size) { try { $util = new \COM('CAPICOM.Utilities.1'); $data = base64_decode($util->GetRandom($size, 0)); return str_pad($data, $size, chr(0)); } catch (\Exception $e) { unset($e); return static::emptyValue($size); } }
public static function RandomBytes($count, $printable = FALSE) { $bytes = ''; // supress warnings when open_basedir restricts access to /dev/urand if (@is_readable('/dev/urandom') && ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) { $bytes = fread($hRand, $count); fclose($hRand); } if (strlen($bytes) < $count && function_exists('mcrypt_create_iv')) { // Use MCRYPT_RAND on Windows hosts with PHP < 5.3.7, otherwise use MCRYPT_DEV_URANDOM // (http://bugs.php.net/55169). if (version_compare(PHP_VERSION, '5.3.7', '<') && strncasecmp(PHP_OS, 'WIN', 3) == 0) { $bytes = mcrypt_create_iv($count, MCRYPT_RAND); } else { $bytes = mcrypt_create_iv($count, MCRYPT_DEV_URANDOM); } } if (strlen($bytes) < $count && function_exists('openssl_random_pseudo_bytes')) { $bytes = openssl_random_pseudo_bytes($count); } if (strlen($bytes) < $count && @class_exists('COM')) { // Officially deprecated in Windows 7 // http://msdn.microsoft.com/en-us/library/aa388182%28v=vs.85%29.aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); if (is_callable(array($CAPI_Util, 'GetRandom'))) { $bytes = $CAPI_Util->GetRandom(16, 0); $bytes = base64_decode($bytes); } } catch (Exception $ex) { } } if (strlen($bytes) < $count) { // This fallback here based on phpass code $bytes = ''; $random_state = microtime(); if (function_exists('getmypid')) { $random_state .= getmypid(); } for ($i = 0; $i < $count; $i += 16) { $random_state = md5(microtime() . $random_state); $bytes .= pack('H*', md5($random_state)); } $bytes = substr($bytes, 0, $count); } if ($printable) { return base64_encode($bytes); } else { return $bytes; } }
/** * Generate a random string of the specified size * * @param int $size The size of the requested random string * * @return string A string of the requested size */ public function generate($size) { if (!class_exists('\\COM', false)) { return str_repeat(chr(0), $size); } try { $util = new \COM('CAPICOM.Utilities.1'); $data = base64_decode($util->GetRandom($size, 0)); return str_pad($data, $size, chr(0)); } catch (\Exception $e) { unset($e); return str_repeat(chr(0), $size); } }
public function randomBytes($byteLength) { if (function_exists('openssl_random_pseudo_bytes')) { $data = openssl_random_pseudo_bytes($byteLength); } elseif (is_readable('/dev/urandom')) { $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== false) { $data = fread($fp, $byteLength); fclose($fp); } } elseif (class_exists('COM')) { // @TODO: Someone care to test on Windows? Not it! try { $capi = new COM('CAPICOM.Utilities.1'); $data = $capi->GetRandom($btyeLength, 0); } catch (Exception $ex) { // Fail silently } } return $data; }
/** * Note: Returned values are not guaranteed to be crypto-safe, * depending on the used retrieval method. * * @return string Returns a random series of bytes */ public function generateEntropy() { $isWin = preg_match('/WIN/', PHP_OS); // TODO Fails with "Could not gather sufficient random data" on IIS, temporarily disabled on windows if (!$isWin) { if (function_exists('mcrypt_create_iv')) { $e = mcrypt_create_iv(64, MCRYPT_DEV_URANDOM); if ($e !== false) { return $e; } } } // Fall back to SSL methods - may slow down execution by a few ms if (function_exists('openssl_random_pseudo_bytes')) { $e = openssl_random_pseudo_bytes(64, $strong); // Only return if strong algorithm was used if ($strong) { return $e; } } // Read from the unix random number generator if (!$isWin && !ini_get('open_basedir') && is_readable('/dev/urandom') && ($h = fopen('/dev/urandom', 'rb'))) { $e = fread($h, 64); fclose($h); return $e; } // Warning: Both methods below are considered weak // try to read from the windows RNG if ($isWin && class_exists('COM')) { try { $comObj = new COM('CAPICOM.Utilities.1'); if (is_callable(array($comObj, 'GetRandom'))) { return base64_decode($comObj->GetRandom(64, 0)); } } catch (Exception $ex) { } } // Fallback to good old mt_rand() return uniqid(mt_rand(), true); }
/** * Returns entropy using a hash of various available methods for obtaining * random data. * The default hash method is "sha1" and the default size is 32. * * @param string $hash * the hash method to use while generating the hash. * @param int $size * the size of random data to use while generating the hash. * @return string the randomized salt */ function zen_get_entropy($hash = 'sha1', $size = 32) { $data = null; if (!in_array($hash, hash_algos())) { $hash = 'sha1'; } if (!is_int($size)) { $size = (int) $size; } // Use openssl if available if (function_exists('openssl_random_pseudo_bytes')) { // echo('Attempting to create entropy using openssl'); $entropy = openssl_random_pseudo_bytes($size, $strong); if ($strong) { $data = $entropy; } unset($strong, $entropy); } // Use mcrypt with /dev/urandom if available if ($data === null && function_exists('mcrypt_create_iv') && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' || version_compare(PHP_VERSION, '5.3.7', '>='))) { // echo('Attempting to create entropy using mcrypt'); $entropy = mcrypt_create_iv($size, MCRYPT_DEV_URANDOM); if ($entropy !== FALSE) { $data = $entropy; } unset($entropy); } if ($data === null) { // Fall back to using /dev/urandom if available $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== FALSE) { // echo('Attempting to create entropy using /dev/urandom'); $entropy = @fread($fp, $size); @fclose($fp); if (strlen($entropy) == $size) { $data = $entropy; } unset($fp, $entropy); } } // Final fallback (mixture of various methods) if ($data === null) { // echo('Attempting to create entropy using FINAL FALLBACK'); if (!defined('DIR_FS_ROOT')) { define('DIR_FS_ROOT', DIR_FS_CATALOG); } $filename = DIR_FS_ROOT . 'includes/configure.php'; $stat = @stat($filename); if ($stat === FALSE) { $stat = array('microtime' => microtime()); } $stat['mt_rand'] = mt_rand(); $stat['file_hash'] = hash_file($hash, $filename, TRUE); // Attempt to get a random value on windows // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx if (@class_exists('COM')) { try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $entropy = $CAPI_Util->GetRandom($size, 0); if ($entropy) { // echo('Adding random data to entropy using CAPICOM.Utilities'); $stat['CAPICOM_Utilities_random'] = md5($entropy, TRUE); } unset($CAPI_Util, $entropy); } catch (Exception $ex) { } } // echo('Adding random data to entropy using file information and contents'); @shuffle($stat); foreach ($stat as $value) { $data .= $value; } unset($filename, $value, $stat); } return hash($hash, $data); }
/** * Windows with PHP < 5.3.0 will not have the function * openssl_random_pseudo_bytes() available, so let's use * CAPICOM to work around this deficiency. * * @param int $bytes * @return string */ function random_bytes($bytes) { try { $buf = ''; $util = new COM('CAPICOM.Utilities.1'); $execs = 0; /** * Let's not let it loop forever. If we run N times and fail to * get N bytes of random data, then CAPICOM has failed us. */ do { $buf .= base64_decode($util->GetRandom($bytes, 0)); if (RandomCompat_strlen($buf) >= $bytes) { return RandomCompat_substr($buf, 0, $bytes); } ++$execs; } while ($execs < $bytes); } catch (Exception $e) { unset($e); // Let's not let CAPICOM errors kill our app } throw new Exception('PHP failed to generate random data.'); }
function generate_random_string($chars = 16) { if (defined('USE_POOR_RANDOMS')) { $options = array_merge(range('a', 'b'), range('A', 'Z'), range(0, 9)); $res = ''; for ($i = 0; $i < $chars; $i++) { $res .= $options[rand(0, count($options) - 1)]; } return $res; } $pr_bits = ''; if (function_exists('openssl_random_pseudo_bytes')) { $pr_bits = openssl_random_pseudo_bytes($chars); } else { // Unix/Linux platform? $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== FALSE) { $pr_bits .= @fread($fp, $chars); @fclose($fp); } // MS-Windows platform? if (@class_exists('COM')) { // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $pr_bits .= $CAPI_Util->GetRandom($chars, 0); // if we ask for binary data PHP munges it, so we // request base64 return value. We squeeze out the // redundancy and useless ==CRLF by hashing... if ($pr_bits) { $pr_bits = md5($pr_bits, TRUE); } } catch (Exception $ex) { // echo 'Exception: ' . $ex->getMessage(); } } } if (empty($pr_bits)) { trigger_error("Could not generate random string", E_USER_ERROR); } if (strlen($pr_bits) < $chars) { trigger_error("Generated random string not long enough (only " . strlen($pr_bits)); } $validChars = array_merge(range(0, 9), range('A', 'Z'), range('a', 'z')); for ($i = 0; $i < strlen($pr_bits); $i++) { if (!preg_match('/[A-Za-z0-9]/', $pr_bits[$i])) { $pr_bits[$i] = $validChars[ord($pr_bits[$i]) % count($validChars)]; } } return $pr_bits; }
/** * Return truly (pseudo) random bytes if available, otherwise fall back to mt_rand * * @author Mark Seecof * @author Michael Hamann <*****@*****.**> * @link http://www.php.net/manual/de/function.mt-rand.php#83655 * @param int $length number of bytes to get * @return string binary random strings */ function auth_randombytes($length) { $strong = false; $rbytes = false; if (function_exists('openssl_random_pseudo_bytes') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { $rbytes = openssl_random_pseudo_bytes($length, $strong); } if (!$strong && function_exists('mcrypt_create_iv') && (version_compare(PHP_VERSION, '5.3.7') >= 0 || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { $rbytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); if ($rbytes !== false && strlen($rbytes) === $length) { $strong = true; } } // If no strong randoms available, try OS the specific ways if (!$strong) { // Unix/Linux platform $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== false) { $rbytes = fread($fp, $length); fclose($fp); } // MS-Windows platform if (class_exists('COM')) { // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $rbytes = $CAPI_Util->GetRandom($length, 0); // if we ask for binary data PHP munges it, so we // request base64 return value. if ($rbytes) { $rbytes = base64_decode($rbytes); } } catch (Exception $ex) { // fail } } } if (strlen($rbytes) < $length) { $rbytes = false; } // still no random bytes available - fall back to mt_rand() if ($rbytes === false) { $rbytes = ''; for ($i = 0; $i < $length; ++$i) { $rbytes .= chr(mt_rand(0, 255)); } } return $rbytes; }
/** * Returns a string of highly randomized bytes (over the full 8-bit range). * * @copyright Drupal CMS * @license GNU General Public License version 2 * @param integer Number of characters (bytes) to return * @return string Random Bytes */ public static function generateRandomBytes($count) { $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') { if (class_exists('COM')) { try { $com = new COM('CAPICOM.Utilities.1'); $output = base64_decode($com->GetRandom($count, 0)); } catch (Exception $e) { // CAPICOM not installed } } 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 = ''; } } } } // fallback if other random byte generation failed until now if (!isset($output[$count - 1])) { // We initialize with the somewhat random. $randomState = $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . base_convert(memory_get_usage() % pow(10, 6), 10, 2) . microtime() . uniqid('') . getmypid(); while (!isset($output[$count - 1])) { $randomState = sha1(microtime() . mt_rand() . $randomState); $output .= sha1(mt_rand() . $randomState, TRUE); } $output = substr($output, strlen($output) - $count, $count); } return $output; }
/** * Uses Windows API to generate a secure password. We basically generate * a random number of $len bytes and convert the resulting binary string * to something user readable. * * This relies on the now obsolete CAPICOM library from MS: * http://www.microsoft.com/en-us/download/details.aspx?id=25281 * Which is no longer supported after Vista. It was replaced with the * .net x509 crypto lib. * * Helper for generate(). * * @param int $len - strength of the password in bytes * * @return a printable password string * */ private function tryWindows($len) { $pr_bits = ""; if (@class_exists('COM')) { // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $pr_bits .= $CAPI_Util->GetRandom($len, 0); // if we ask for binary data PHP munges it, so we // request base64 return value. We squeeze out the // redundancy and useless ==CRLF by hashing... if ($pr_bits) { $pr_bits = $this->binconvert($pr_bits, true); } } catch (Exception $ex) { return ""; } } return $pr_bits; }
public function entropy($size = 23) { // use mcrypt with urandom if we're on 5.3+ if (version_compare(PHP_VERSION, '5.3.0', '>=')) { return mcrypt_create_iv($size, MCRYPT_DEV_URANDOM); } // otherwise try ssl (beware - it may slow down your app by a few milliseconds) if (function_exists('openssl_random_pseudo_bytes')) { $entropy = openssl_random_pseudo_bytes($size, $strong); // skip ssl since it wasn't using the strong algo if ($strong) { return $entropy; } } // try to read from the unix RNG if (is_readable('/dev/urandom') && ($handle = fopen('/dev/urandom', 'rb'))) { $entropy = fread($handle, $size); fclose($handle); return $entropy; } // Warning ! // from here on, the entropy is considered weak // so you may want to consider just throwing // an exception to realize that your code is running // in an insecure way // try to read from the windows RNG if (class_exists('COM', FALSE)) { try { $com = new \COM('CAPICOM.Utilities.1'); $entropy = base64_decode($com->GetRandom($size, 0)); return $entropy; } catch (Exception $e) { throw new \ErrorException($e); } } // last solution.. barely better than nothing return substr(uniqid(mt_rand(), true), $size); }
/** * Read random bytes from /dev/urandom or equivalent. See also * @{method:readRandomCharacters}. * * @param int Number of bytes to read. * @return string Random bytestring of the provided length. * * @task file * * @phutil-external-symbol class COM */ public static function readRandomBytes($number_of_bytes) { if (phutil_is_windows()) { if (!class_exists('COM')) { throw new FilesystemException('CAPICOM.Utilities.1', "Class 'COM' does not exist, you must enable php_com_dotnet.dll."); } try { $com = new COM('CAPICOM.Utilities.1'); } catch (Exception $ex) { throw new FilesystemException('CAPICOM.Utilities.1', 'Unable to load DLL, follow instructions at ' . 'https://bugs.php.net/48498.'); } try { return $com->GetRandom($number_of_bytes); } catch (Exception $ex) { throw new FilesystemException('CAPICOM.Utilities.1', 'Unable to read random bytes through CAPICOM!'); } } $urandom = @fopen('/dev/urandom', 'rb'); if (!$urandom) { throw new FilesystemException('/dev/urandom', 'Failed to open /dev/urandom for reading!'); } $data = @fread($urandom, $number_of_bytes); if (strlen($data) != $number_of_bytes) { throw new FilesystemException('/dev/urandom', 'Failed to read random bytes!'); } @fclose($urandom); return $data; }
/** {@inheritDoc} */ public function generateSalt() { $api = new COM('CAPICOM.Utilities.1'); return $this->processSalt($api->GetRandom(22, 0)); }
public static function secureRandom($bits = 16) { $bytes = $bits / 8; $result = ''; $digits = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); $pr_bits = ''; #Unix/Linux platform try { $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== false) { $pr_bits .= @fread($fp, $bytes); @fclose($fp); } } catch (Exception $e) { } #MS-Windows platform before CAPICOM discontinued if (@class_exists('COM')) { #http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $pr_bits .= $CAPI_Util->GetRandom($bytes, 0); #ask for binary data PHP munges it, so we #request base64 return value. We squeeze out the #redundancy and useless ==CRLF by hashing... if ($pr_bits) { $pr_bits = md5($pr_bits, true); } } catch (Exception $e) { } } #nothing has worked yet so lets make an outside connection if (strlen($pr_bits) < $bytes) { try { $pr_bits = file_get_contents("http://www.random.org/cgi-bin/randbyte?nbytes={$bytes}&format=h"); #connect to random.org for the random stuff $pr_bits = preg_replace('/[^0-9A-z]/', '', trim($pr_bits)); #git rid of the spaces, only leaves the 16 bits or 32 characters $pr_bits = pack("H*", $pr_bits); #pack it down into the 16 byte string } catch (Exception $e) { } } #failed to get any random source to work if (strlen($pr_bits) < $bytes) { throw new NoRandomProviderException(); return false; } $len = strlen($pr_bits); $b = 0; for ($i = 0; $i < $len; $i++) { $b = ord($pr_bits[$i]); $result = $result . $digits[($b & 0xf0) >> 4]; $result = $result . $digits[$b & 0xf]; } return $result; }
/** * Returns a random "salt" value, to be used when "hashing" a password * using a one-way encryption algorithm, to prevent an attack using a "rainbow table" * Tryes to use the best available random number generator * @return string The generated random "salt" */ static function GetNewSalt() { // Copied from http://www.php.net/manual/en/function.mt-rand.php#83655 // get 128 pseudorandom bits in a string of 16 bytes $sRandomBits = null; // Unix/Linux platform? $fp = @fopen('/dev/urandom', 'rb'); if ($fp !== FALSE) { //echo "Random bits pulled from /dev/urandom<br/>\n"; $sRandomBits .= @fread($fp, 16); @fclose($fp); } else { // MS-Windows platform? if (@class_exists('COM')) { // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $sBase64RandomBits = '' . $CAPI_Util->GetRandom(16, 0); // if we ask for binary data PHP munges it, so we // request base64 return value. We squeeze out the // redundancy and useless ==CRLF by hashing... if ($sBase64RandomBits) { //echo "Random bits got from CAPICOM.Utilities.1<br/>\n"; $sRandomBits = md5($sBase64RandomBits, TRUE); } } catch (Exception $ex) { // echo 'Exception: ' . $ex->getMessage(); } } } if ($sRandomBits == null) { // No "strong" random generator available, use PHP's built-in mechanism //echo "Random bits generated from mt_rand<br/>\n"; mt_srand(crc32(microtime())); $sRandomBits = ''; for ($i = 0; $i < 4; $i++) { $sRandomBits .= sprintf('%04x', mt_rand(0, 65535)); } } return $sRandomBits; }
/** * Returns a securely generated seed for PHP's RNG (Random Number Generator) * * @param int Length of the seed bytes (8 is default. Provides good cryptographic variance) * @return int An integer equivalent of a secure hexadecimal seed */ function secure_seed_rng($count = 8) { $output = ''; // DIRECTORY_SEPARATOR checks if running windows if (DIRECTORY_SEPARATOR != '\\') { // Unix/Linux // Use OpenSSL when available if (function_exists('openssl_random_pseudo_bytes')) { $output = openssl_random_pseudo_bytes($count); } elseif (function_exists('mcrypt_create_iv')) { $output = mcrypt_create_iv($count, MCRYPT_DEV_URANDOM); } elseif (@is_readable('/dev/urandom') && ($handle = @fopen('/dev/urandom', 'rb'))) { $output = @fread($handle, $count); @fclose($handle); } } else { // Windows // Use OpenSSL when available // PHP <5.3.4 had a bug which makes that function unusable on Windows if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) { $output = openssl_random_pseudo_bytes($count); } elseif (function_exists('mcrypt_create_iv')) { $output = mcrypt_create_iv($count, MCRYPT_RAND); } elseif (class_exists('COM')) { try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); if (is_callable(array($CAPI_Util, 'GetRandom'))) { $output = $CAPI_Util->GetRandom($count, 0); } } catch (Exception $e) { } } } // Didn't work? Do we still not have enough bytes? Use our own (less secure) rng generator if (strlen($output) < $count) { $output = ''; // Close to what PHP basically uses internally to seed, but not quite. $unique_state = microtime() . @getmypid(); for ($i = 0; $i < $count; $i += 16) { $unique_state = md5(microtime() . $unique_state); $output .= pack('H*', md5($unique_state)); } } // /dev/urandom and openssl will always be twice as long as $count. base64_encode will roughly take up 33% more space but crc32 will put it to 32 characters $output = hexdec(substr(dechex(crc32(base64_encode($output))), 0, $count)); return $output; }
/** * Get random bytes * * @ref https://github.com/paragonie/random_compat/ * * @param int $length Output length * * @return string|false false on error */ public static function get_random_bytes($length) { if (!$length || !ctype_digit((string) $length)) { return false; } else { $length = (int) $length; } if (function_exists('random_bytes') && self::is_php('7.0')) { /** * PHP 7 -> http://php.net/manual/de/function.random-bytes.php */ try { $return = random_bytes($length); } catch (\Exception $e) { $return = false; } return $return; } else { /** * PHP 5.2.0 - 5.6.x way to implement random_bytes() * * // WARNING: Unfortunately, none of the following PRNGs is guaranteed to exist ... * * In order of preference: * 1. PHP-Module: "mcrypt" via mcrypt_create_iv() * 2. Linux / BSD: "/dev/urandom" via fread() * 3. Windows: \COM('CAPICOM.Utilities.1')->GetRandom() * 4. PHP+OpenSSL: openssl_random_pseudo_bytes() */ /** * 1. PHP-Module */ if (extension_loaded('mcrypt') && defined(MCRYPT_DEV_URANDOM) === true) { $output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); if ($output !== false && UTF8::strlen($output, '8bit') === $length) { return $output; } } /** * 2. Linux / BSD */ if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { $fp = fopen('/dev/urandom', 'rb'); if (!empty($fp)) { $st = fstat($fp); // In C, this would be: (stat_mode & S_IFMT) !== S_IFCHR if (($st['mode'] & 0170000) !== 020000) { fclose($fp); $fp = false; } unset($st); } } if (isset($fp) && $fp !== false) { /** * stream_set_read_buffer() / stream_set_chunk_size 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 (function_exists('stream_set_chunk_size')) { stream_set_chunk_size($fp, $length); } if (function_exists('stream_set_read_buffer')) { stream_set_read_buffer($fp, $length); } $remaining = $length; $buf = ''; do { $read = fread($fp, $remaining); // We cannot safely read from the file, so exit the do-while loop. if ($read === false) { $buf = false; break; } // Decrease the number of bytes returned from remaining. $remaining -= UTF8::strlen($read, '8bit'); $buf .= $read; } while ($remaining > 0); fclose($fp); if ($buf !== false) { if (UTF8::strlen($buf, '8bit') === $length) { return $buf; } } } /* * 3. Windows * * PHP can be used to access COM objects on Windows platforms * * --- * * PROBLEM: you see this error-message: * com_exception thrown with message * "Failed to create COM object `CAPICOM.Utilities.1': Ungültige Syntax * * SOLUTION: register the dll: * regsvr32 c:\windows\capicom.dll * * --- * * @ref http://php.net/manual/en/ref.com.php */ if (extension_loaded('com_dotnet') && class_exists('COM') === true) { // init $buf = ''; /** @noinspection PhpUndefinedClassInspection */ $util = new \COM('CAPICOM.Utilities.1'); /** * Let's not let it loop forever. If we run N times and fail to * get N bytes of random data, then CAPICOM has failed us. */ $execCount = 0; do { /** @noinspection PhpUndefinedMethodInspection */ $buf .= base64_decode($util->GetRandom($length, 0)); if (UTF8::strlen($buf, '8bit') >= $length) { return UTF8::substr($buf, 0, $length); } ++$execCount; } while ($execCount < $length); } /** * 4. PHP + OpenSSL * * fallback to "openssl_random_pseudo_bytes()" */ if (function_exists('openssl_random_pseudo_bytes')) { $output = openssl_random_pseudo_bytes($length, $strong); if ($output !== false && $strong === true) { if (UTF8::strlen($output, '8bit') === $length) { return $output; } } } return false; } }
/** * Generate random bytes for high entropy * * @since 1.3.6 * * @return string String of random bytes **/ private function entropy() { $entropy = ''; if (function_exists('openssl_random_pseudo_bytes')) { $entropy = openssl_random_pseudo_bytes(64, $strong); // Don't use openssl if a strong crypto algo wasn't used if ($strong !== true) { $entropy = ''; } } $entropy .= uniqid(mt_rand(), true); // Check for open_basedir restrictions $openbasedir = false === strpos(ini_get('open_basedir'), DIRECTORY_SEPARATOR); // Try adding entropy from the Unix random number generator if ($openbasedir && @is_readable('/dev/urandom') && ($h = fopen('/dev/urandom', 'rb'))) { if (function_exists('stream_set_read_buffer')) { stream_set_read_buffer($h, 0); } $entropy .= @fread($h, 64); fclose($h); } // Try adding entropy from the Windows random number generator if (class_exists('COM')) { try { $CAPICOM = new COM('CAPICOM.Utilities.1'); $entropy .= base64_decode($CAPICOM->GetRandom(64, 0)); } catch (Exception $E) { } } return $entropy; }