/** * Generate a random number * * @param optional Integer $min * @param optional Integer $max * @return BigInteger * @access public */ function random($min = false, $max = false) { if ($min === false) { $min = new BigInteger(0); } if ($max === false) { $max = new BigInteger(0x7fffffff); } $compare = $max->compare($min); if (!$compare) { return $this->_normalize($min); } else { if ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; $min = $temp; } } $generator = $this->generator; $max = $max->subtract($min); $max = ltrim($max->toBytes(), chr(0)); $size = strlen($max) - 1; $random = ''; $bytes = $size & 1; for ($i = 0; $i < $bytes; ++$i) { $random .= chr($generator(0, 255)); } $blocks = $size >> 1; for ($i = 0; $i < $blocks; ++$i) { // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems $random .= pack('n', $generator(0, 0xffff)); } $temp = new BigInteger($random, 256); if ($temp->compare(new BigInteger(substr($max, 1), 256)) > 0) { $random = chr($generator(0, ord($max[0]) - 1)) . $random; } else { $random = chr($generator(0, ord($max[0]))) . $random; } $random = new BigInteger($random, 256); return $this->_normalize($random->add($min)); }
/** * Generate a random prime number. * * If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed, * give up and return false. * * @param optional Integer $min * @param optional Integer $max * @param optional Integer $timeout * @return BigInteger * @access public * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}. */ function randomPrime($min = false, $max = false, $timeout = false) { if ($min === false) { $min = new BigInteger(0); } if ($max === false) { $max = new BigInteger(0x7fffffff); } $compare = $max->compare($min); if (!$compare) { return $min->isPrime() ? $min : false; } else { if ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; $min = $temp; } } static $one, $two; if (!isset($one)) { $one = new BigInteger(1); $two = new BigInteger(2); } $start = time(); $x = $this->random($min, $max); // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>. if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime')) { $p = new BigInteger(); $p->value = gmp_nextprime($x->value); if ($p->compare($max) <= 0) { return $p; } if (!$min->equals($x)) { $x = $x->subtract($one); } return $x->randomPrime($min, $x); } if ($x->equals($two)) { return $x; } $x->_make_odd(); if ($x->compare($max) > 0) { // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range if ($min->equals($max)) { return false; } $x = $min->copy(); $x->_make_odd(); } $initial_x = $x->copy(); while (true) { if ($timeout !== false && time() - $start > $timeout) { return false; } if ($x->isPrime()) { return $x; } $x = $x->add($two); if ($x->compare($max) > 0) { $x = $min->copy(); if ($x->equals($two)) { return $x; } $x->_make_odd(); } if ($x->equals($initial_x)) { return false; } } }
/** * Get the index of a revoked certificate. * * @param array $rclist * @param String $serial * @param Boolean $create optional * @access private * @return Integer or false */ function _revokedCertificate(&$rclist, $serial, $create = false) { $serial = new BigInteger($serial); foreach ($rclist as $i => $rc) { if (!$serial->compare($rc['userCertificate'])) { return $i; } } if (!$create) { return false; } $i = count($rclist); $rclist[] = array('userCertificate' => $serial, 'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O'))); return $i; }