Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #3 from ezimuel/seed-improved

Added entropy sources + unit test
  • Loading branch information...
commit 85ef83620e5c7dffc53320d6d5549ca5f65272d3 2 parents 8aba60f + c6db24e
@GeorgeArgyros authored
Showing with 64 additions and 37 deletions.
  1. +16 −0 demo.php
  2. +29 −37 srand.php
  3. +19 −0 tests/SrandTest.php
View
16 demo.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Demo of usage secyre_random_bytes() function
+ *
+ */
+require_once 'srand.php';
+
+$c1 = microtime(true);
+if (isset($_GET['l'])) {
+ $t = secure_random_bytes($_GET['l']);
+} else {
+ $t = secure_random_bytes();
+}
+$c2 = microtime(true);
+
+echo "Token: $t<br>Execution time: " . (int)(($c2-$c1)*1000000);
View
66 srand.php
@@ -48,8 +48,9 @@ function secure_random_bytes($len = 10)
substr(PHP_OS, 0, 3) !== 'WIN'))
{
$SSLstr = openssl_random_pseudo_bytes($len, $strong);
- if ($strong)
+ if ($strong) {
return $SSLstr;
+ }
}
/*
@@ -57,15 +58,16 @@ function secure_random_bytes($len = 10)
* the operating system's PRNG. This is better than reading /dev/urandom
* directly since it avoids reading larger blocks of data than needed.
* Older versions of mcrypt_create_iv may be broken or take too much time
- * to finish so we only use this function with PHP 5.3 and above.
+ * to finish so we only use this function with PHP 5.3.7 and above.
+ * @see https://bugs.php.net/bug.php?id=55169
*/
if (function_exists('mcrypt_create_iv') &&
- (version_compare(PHP_VERSION, '5.3.0') >= 0 ||
- substr(PHP_OS, 0, 3) !== 'WIN'))
- {
+ (version_compare(PHP_VERSION, '5.3.7') >= 0 ||
+ substr(PHP_OS, 0, 3) !== 'WIN')) {
$str = mcrypt_create_iv($len, MCRYPT_DEV_URANDOM);
- if ($str !== false)
+ if ($str !== false) {
return $str;
+ }
}
@@ -83,9 +85,10 @@ function secure_random_bytes($len = 10)
$total = $len; // total bytes of entropy to collect
$handle = @fopen('/dev/urandom', 'rb');
- if ($handle && function_exists('stream_set_read_buffer'))
+ if ($handle && function_exists('stream_set_read_buffer')) {
@stream_set_read_buffer($handle, 0);
-
+ }
+
do
{
$bytes = ($total > $hash_len)? $hash_len : $total;
@@ -94,20 +97,23 @@ function secure_random_bytes($len = 10)
//collect any entropy available from the PHP system and filesystem
$entropy = rand() . uniqid(mt_rand(), true) . $SSLstr;
$entropy .= implode('', @fstat(@fopen( __FILE__, 'r')));
- $entropy .= memory_get_usage();
- if ($handle)
- {
- $entropy .= @fread($handle, $bytes);
+ $entropy .= memory_get_usage() . getmypid();
+ $entropy .= serialize($_ENV) . serialize($_SERVER);
+ if (function_exists('posix_times')) {
+ $entropy .= serialize(posix_times());
+ }
+ if (function_exists('zend_thread_id')) {
+ $entropy .= zend_thread_id();
}
- else
- {
+ if ($handle) {
+ $entropy .= @fread($handle, $bytes);
+ } else {
// Measure the time that the operations will take on average
- for ($i = 0; $i < 3; $i ++)
+ for ($i = 0; $i < 3; $i++)
{
$c1 = microtime(true);
$var = sha1(mt_rand());
- for ($j = 0; $j < 50; $j++)
- {
+ for ($j = 0; $j < 50; $j++) {
$var = sha1($var);
}
$c2 = microtime(true);
@@ -116,17 +122,15 @@ function secure_random_bytes($len = 10)
// Based on the above measurement determine the total rounds
// in order to bound the total running time.
- $rounds = (int)($msec_per_round*50 / (int)(($c2-$c1)*1000000));
+ $rounds = (int) ($msec_per_round * 50 / (int) (($c2 - $c1) * 1000000));
// Take the additional measurements. On average we can expect
// at least $bits_per_round bits of entropy from each measurement.
- $iter = $bytes*(int)(ceil(8 / $bits_per_round));
- for ($i = 0; $i < $iter; $i ++)
- {
+ $iter = $bytes * (int) (ceil(8 / $bits_per_round));
+ for ($i = 0; $i < $iter; $i++) {
$c1 = microtime();
$var = sha1(mt_rand());
- for ($j = 0; $j < $rounds; $j++)
- {
+ for ($j = 0; $j < $rounds; $j++) {
$var = sha1($var);
}
$c2 = microtime();
@@ -138,20 +142,8 @@ function secure_random_bytes($len = 10)
$str .= sha1($entropy, true);
} while ($len > strlen($str));
- if ($handle)
+ if ($handle) {
@fclose($handle);
-
+ }
return substr($str, 0, $len);
}
-
-
-$c1 = microtime(true);
-if (isset($_GET['l']))
- $t = secure_random_bytes($_GET['l']);
-else
- $t = secure_random_bytes();
-$c2 = microtime(true);
-
-echo "Token: $t<br>Execution time: " . (int)(($c2-$c1)*1000000);
-?>
-
View
19 tests/SrandTest.php
@@ -0,0 +1,19 @@
+<?php
+namespace SrandTest;
+
+require_once '../srand.php';
+
+class SrandTest extends \PHPUnit_Framework_TestCase
+{
+
+ public function testRandBytes()
+ {
+ for ($length = 1; $length < 4096; $length++) {
+ $rand = secure_random_bytes($length);
+ $this->assertTrue($rand !== false);
+ $this->assertEquals($length, strlen($rand));
+ }
+ }
+
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.