Updated secure random number generator ith harder entropy distillation

This commit is contained in:
Shoghi Cervantes
2013-06-02 18:01:34 +02:00
parent ec22034ad7
commit a8b8427065

View File

@ -241,6 +241,7 @@ class Utils{
} }
public static function getRandomBytes($length = 16, $secure = true, $raw = true, $startEntropy = "", &$rounds = 0, &$drop = 0){ public static function getRandomBytes($length = 16, $secure = true, $raw = true, $startEntropy = "", &$rounds = 0, &$drop = 0){
static $lastRandom = "";
$output = b""; $output = b"";
$length = abs((int) $length); $length = abs((int) $length);
$secureValue = ""; $secureValue = "";
@ -255,65 +256,76 @@ class Utils{
PHP_OS, PHP_OS,
microtime(), microtime(),
(string) lcg_value(), (string) lcg_value(),
(string) PHP_MAXPATHLEN,
PHP_SAPI,
(string) PHP_INT_MAX.".".PHP_INT_SIZE,
serialize($_SERVER), serialize($_SERVER),
serialize(get_defined_constants()), serialize(get_defined_constants()),
get_current_user(), get_current_user(),
serialize(ini_get_all()), serialize(ini_get_all()),
(string) memory_get_usage(), (string) memory_get_usage().".".memory_get_peak_usage(),
php_uname(), php_uname(),
phpversion(), phpversion(),
extension_loaded("gmp") ? gmp_strval(gmp_random(4)):microtime(), extension_loaded("gmp") ? gmp_strval(gmp_random(4)):microtime(),
zend_version(), zend_version(),
(string) getmypid(), (string) getmypid(),
(string) getmyuid(),
(string) mt_rand(), (string) mt_rand(),
(string) getmyinode(),
(string) getmygid(),
(string) rand(), (string) rand(),
function_exists("zend_thread_id") ? ((string) zend_thread_id()):microtime(), function_exists("zend_thread_id") ? ((string) zend_thread_id()):microtime(),
function_exists("sys_getloadavg") ? print_r(sys_getloadavg(), true):microtime(), function_exists("getrusage") ? @implode(getrusage()):microtime(),
function_exists("sys_getloadavg") ? @implode(sys_getloadavg()):microtime(),
serialize(get_loaded_extensions()), serialize(get_loaded_extensions()),
sys_get_temp_dir(), sys_get_temp_dir(),
(string) disk_free_space("."), (string) disk_free_space("."),
(string) disk_total_space("."), (string) disk_total_space("."),
uniqid(microtime(),true), uniqid(microtime(),true),
file_exists("/proc/cpuinfo") ? file_get_contents("/proc/cpuinfo") : microtime(),
); );
shuffle($weakEntropy); shuffle($weakEntropy);
$value = hash("sha256", implode($weakEntropy), true); $value = hash("sha512", implode($weakEntropy), true);
$lastRandom .= $value;
foreach($weakEntropy as $k => $c){ //mixing entropy values with XOR and hash randomness extractor foreach($weakEntropy as $k => $c){ //mixing entropy values with XOR and hash randomness extractor
$c = (string) $c; $value ^= hash("sha256", $c . microtime() . $k, true) . hash("sha256", mt_rand() . microtime() . $k . $c, true);
str_shuffle($c); //randomize characters $value ^= hash("sha512", ((string) lcg_value()) . $c . microtime() . $k, true);
$value ^= hash("md5", $c . microtime() . $k, true) . hash("md5", microtime() . $k . $c, true);
$value ^= hash("sha256", $c . microtime() . $k, true);
} }
unset($weakEntropy); unset($weakEntropy);
if($secure === true){ if($secure === true){
$strongEntropy = array( $strongEntropyValues = array(
is_array($startEntropy) ? $startEntropy[($rounds + $drop) % count($startEntropy)]:$startEntropy, //Get a random index of the startEntropy, or just read it is_array($startEntropy) ? hash("sha512", $startEntropy[($rounds + $drop) % count($startEntropy)], true):hash("sha512", $startEntropy, true), //Get a random index of the startEntropy, or just read it
file_exists("/dev/urandom") ? fread(fopen("/dev/urandom", "rb"), 512):"", file_exists("/dev/urandom") ? fread(fopen("/dev/urandom", "rb"), 64) : str_repeat("\x00", 64),
(function_exists("openssl_random_pseudo_bytes") and version_compare(PHP_VERSION, "5.3.4", ">=")) ? openssl_random_pseudo_bytes(512):"", (function_exists("openssl_random_pseudo_bytes") and version_compare(PHP_VERSION, "5.3.4", ">=")) ? openssl_random_pseudo_bytes(64) : str_repeat("\x00", 64),
function_exists("mcrypt_create_iv") ? mcrypt_create_iv(512, MCRYPT_DEV_URANDOM) : "", function_exists("mcrypt_create_iv") ? mcrypt_create_iv(64, MCRYPT_DEV_URANDOM) : str_repeat("\x00", 64),
$value, $value,
); );
shuffle($strongEntropy); $strongEntropy = array_pop($strongEntropyValues);
$strongEntropy = implode($strongEntropy); foreach($strongEntropyValues as $value){
$strongEntropy = $strongEntropy ^ $value;
}
$value = ""; $value = "";
//Von Neumann randomness extractor, increases entropy //Von Neumann randomness extractor, increases entropy
$len = strlen($strongEntropy) * 8; $bitcnt = 0;
for($i = 0; $i < $len; $i += 2){ for($j = 0; $j < 64; ++$j){
$a = ord($strongEntropy{$i >> 3}); $a = ord($strongEntropy{$j});
$b = 1 << ($i % 8); for($i = 0; $i < 8; $i += 2){
$c = 1 << (($i % 8) + 1); $b = ($a & (1 << $i)) > 0 ? 1:0;
$b = ($a & $b) === $b ? "1":"0"; if($b != (($a & (1 << ($i + 1))) > 0 ? 1:0)){
$c = ($a & $c) === $c ? "1":"0"; $secureValue |= $b << $bitcnt;
if($b !== $c){ if($bitcnt == 7){
$secureValue .= $b; $value .= chr($secureValue);
if(isset($secureValue{7})){ $secureValue = 0;
$value .= chr(bindec($secureValue)); $bitcnt = 0;
$secureValue = ""; }else{
++$bitcnt;
}
++$drop;
}else{
$drop += 2;
} }
++$drop;
}else{
$drop += 2;
} }
} }
} }
@ -321,6 +333,7 @@ class Utils{
unset($value); unset($value);
++$rounds; ++$rounds;
} }
$lastRandom = hash("sha512", $lastRandom, true);
return $raw === false ? bin2hex($output):$output; return $raw === false ? bin2hex($output):$output;
} }