note 114898 added to function.mt-rand
| From: | github.com/elcodedocle | Date: | Tue, 22 Apr 2014 18:00:15 +0000 |
| Subject: | note 114898 added to function.mt-rand | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-199318@lists.php.net to get a copy of this message | ||
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
----
Server IP: 80.64.47.13
Probable Submitter: 84.79.71.95
----
Manual Page -- http://php.net/manual/en/function.mt-rand.php
Edit -- https://master.php.net/note/edit/114898
Del: integrated -- https://master.php.net/note/delete/114898/integrated
Del: useless -- https://master.php.net/note/delete/114898/useless
Del: bad code -- https://master.php.net/note/delete/114898/bad+code
Del: spam -- https://master.php.net/note/delete/114898/spam
Del: non-english -- https://master.php.net/note/delete/114898/non-english
Del: in docs -- https://master.php.net/note/delete/114898/in+docs
Del: other reasons-- https://master.php.net/note/delete/114898
Reject -- https://master.php.net/note/reject/114898
Search -- https://master.php.net/manage/user-notes.php