note 114898 deleted from function.mt-rand by cmb

From: Date: Sun, 10 Nov 2019 12:44:13 +0000
Subject: note 114898 deleted from function.mt-rand by cmb
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-212996@lists.php.net to get a copy of this message
Note Submitter: github.com/elcodedocle ---- Ever wanted a crypto safe mt_rand()? Not useful for many things I guess (maybe not useful at all), but I recently wanted to build a class able to pick random words from a dictionary in a safe way, so they could be used as passwords. I probably overdid it... The result is my attempt on a "cryptographically secure" mt_rand implementation including a wrapper for selecting and using the best random bytes generator from available extensions and /dev/urandom (about 100 times slower than mt_rand on a single core, by the way, so it's clearly open for improvement if you want to fork it on github.com/elcodedocle/cryptosecureprng, where you can find the docs to it too). Here is the minimized version (note too long): <?php /** * Crypto Secure PRNG * @copyright 2014 elcodedocle */ class CryptoSecurePRNG { private $intByteCount = 4; private $defaultMax = 2147483647; private $mcrypt; private $openssl; private $urandomFileHandler = false; public function getRandomBytesString($byteCount){ $chars = ''; if ($this->mcrypt) { $chars = mcrypt_create_iv($byteCount, MCRYPT_DEV_URANDOM); } if (!$chars && $this->openssl) { $chars = openssl_random_pseudo_bytes($byteCount); } if (!$chars && is_resource($this->urandomFileHandler)) { while (($len = strlen($chars))< $byteCount) { $chars .= fread($this->urandomFileHandler, $byteCount - $len); } } if ($len = strlen($chars) < $byteCount) { for ($i=0;$i<$len;$i++) { $chars[$i] = $chars[$i] ^ chr(mt_rand(0, 255)); } for ($i = $len; $i < $byteCount; $i++) { $chars .= chr(mt_rand(0, 255)); } } return $chars; } public function rand($min = 0, $max = null){ if ($max === null) { $max = $this->defaultMax; } if (!is_int($min)||!is_int($max)) { throw new Exception('$min and $max must be integers'); } if ($min>$max) { throw new Exception('$min must be <= $max'); } $chars = $this->getRandomBytesString($this->intByteCount); $n = 0; for ($i=0;$i<strlen($chars);$i++) {$n|=(ord($chars[$i])<<(8*(strlen($chars)-$i-1)));} return (abs($n)%($max-$min+1))+$min; } public function __construct(){ $this->mcrypt = function_exists('mcrypt_create_iv'); $this->openssl = function_exists('openssl_random_pseudo_bytes'); if (is_readable('/dev/urandom')){ $this->urandomFileHandler = fopen('/dev/urandom', 'r'); } } public function __destruct(){ if (is_resource($this->urandomFileHandler )) fclose($this->urandomFileHandler); } } $randGen = new CryptoSecurePRNG(); echo $randGen->rand(); //outputs rand int between 0 and 2^32

« previous php.notes (#212996) next »