diff --git a/security/RandomGenerator.php b/security/RandomGenerator.php new file mode 100644 index 000000000..4a7e4b788 --- /dev/null +++ b/security/RandomGenerator.php @@ -0,0 +1,63 @@ +=')) { + return mcrypt_create_iv(64, MCRYPT_DEV_URANDOM); + } + + // 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 (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 (class_exists('COM')) { + try { + $comObj = new COM('CAPICOM.Utilities.1'); + $e = base64_decode($comObj->GetRandom(64, 0)); + return $e; + } catch (Exception $ex) { + } + } + + // Fallback to good old mt_rand() + return uniqid(mt_rand(), true); + } + + /** + * Generates a hash suitable for manual session identifiers, CSRF tokens, etc. + * + * @param String $algorithm Any identifier listed in hash_algos() (Default: whirlpool) + * If possible, choose a slow algorithm which complicates brute force attacks. + * @return String Returned length will depend on the used $algorithm + */ + function generateHash($algorithm = 'whirlpool') { + return hash($algorithm, $this->generateEntropy()); + } + +} \ No newline at end of file diff --git a/tests/security/RandomGeneratorTest.php b/tests/security/RandomGeneratorTest.php new file mode 100644 index 000000000..2a41ecdfa --- /dev/null +++ b/tests/security/RandomGeneratorTest.php @@ -0,0 +1,27 @@ +assertNotNull($r->generateEntropy()); + $this->assertNotEquals($r->generateEntropy(), $r->generateEntropy()); + } + + function testGenerateHash() { + $r = new RandomGenerator(); + $this->assertNotNull($r->generateHash()); + $this->assertNotEquals($r->generateHash(), $r->generateHash()); + } + + function testGenerateHashWithAlgorithm() { + $r = new RandomGenerator(); + $this->assertNotNull($r->generateHash('md5')); + $this->assertNotEquals($r->generateHash(), $r->generateHash('md5')); + } + +} \ No newline at end of file