mirror of
https://github.com/danog/phpseclib.git
synced 2025-01-22 04:51:19 +01:00
- rewrote randomPrime()
- fixed a bug in Math_BigInteger::equals() that only manifests itself when the bcmath extension is used git-svn-id: http://phpseclib.svn.sourceforge.net/svnroot/phpseclib/trunk@90 21d32557-59b3-4da0-833f-c5933fad653e
This commit is contained in:
parent
f2ccfdb0ac
commit
d574a6770e
@ -67,7 +67,7 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMVI Jim Wigginton
|
* @copyright MMVI Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: BigInteger.php,v 1.28 2010-02-07 01:54:51 terrafrost Exp $
|
* @version $Id: BigInteger.php,v 1.29 2010-02-21 07:45:31 terrafrost Exp $
|
||||||
* @link http://pear.php.net/package/Math_BigInteger
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -516,9 +516,9 @@ class Math_BigInteger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (bccomp($current, '0', 0) > 0) {
|
while (bccomp($current, '0', 0) > 0) {
|
||||||
$temp = bcmod($current, 0x1000000);
|
$temp = bcmod($current, '16777216');
|
||||||
$value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
|
$value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
|
||||||
$current = bcdiv($current, 0x1000000, 0);
|
$current = bcdiv($current, '16777216', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->precision > 0 ?
|
return $this->precision > 0 ?
|
||||||
@ -1369,7 +1369,7 @@ class Math_BigInteger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static $zero;
|
static $zero;
|
||||||
if (!isset($zero)) {
|
if ( !isset($zero) ) {
|
||||||
$zero = new Math_BigInteger();
|
$zero = new Math_BigInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2571,6 +2571,7 @@ class Math_BigInteger {
|
|||||||
* @param Array $y_value
|
* @param Array $y_value
|
||||||
* @param Boolean $y_negative
|
* @param Boolean $y_negative
|
||||||
* @return Integer
|
* @return Integer
|
||||||
|
* @see compare()
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _compare($x_value, $x_negative, $y_value, $y_negative)
|
function _compare($x_value, $x_negative, $y_value, $y_negative)
|
||||||
@ -2614,7 +2615,7 @@ class Math_BigInteger {
|
|||||||
case MATH_BIGINTEGER_MODE_GMP:
|
case MATH_BIGINTEGER_MODE_GMP:
|
||||||
return gmp_cmp($this->value, $x->value) == 0;
|
return gmp_cmp($this->value, $x->value) == 0;
|
||||||
default:
|
default:
|
||||||
return $this->value == $x->value && $this->is_negative == $x->is_negative;
|
return $this->value === $x->value && $this->is_negative == $x->is_negative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2816,7 +2817,7 @@ class Math_BigInteger {
|
|||||||
case MATH_BIGINTEGER_MODE_GMP:
|
case MATH_BIGINTEGER_MODE_GMP:
|
||||||
static $two;
|
static $two;
|
||||||
|
|
||||||
if (empty($two)) {
|
if (!isset($two)) {
|
||||||
$two = gmp_init('2');
|
$two = gmp_init('2');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2854,7 +2855,7 @@ class Math_BigInteger {
|
|||||||
case MATH_BIGINTEGER_MODE_GMP:
|
case MATH_BIGINTEGER_MODE_GMP:
|
||||||
static $two;
|
static $two;
|
||||||
|
|
||||||
if (empty($two)) {
|
if (!isset($two)) {
|
||||||
$two = gmp_init('2');
|
$two = gmp_init('2');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3025,6 +3026,17 @@ class Math_BigInteger {
|
|||||||
*/
|
*/
|
||||||
function randomPrime($min = false, $max = false, $timeout = false)
|
function randomPrime($min = false, $max = false, $timeout = false)
|
||||||
{
|
{
|
||||||
|
$compare = $max->compare($min);
|
||||||
|
|
||||||
|
if (!$compare) {
|
||||||
|
return $min;
|
||||||
|
} else if ($compare < 0) {
|
||||||
|
// if $min is bigger then $max, swap $min and $max
|
||||||
|
$temp = $max;
|
||||||
|
$max = $min;
|
||||||
|
$min = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
|
// 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') ) {
|
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
|
||||||
// we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function
|
// we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function
|
||||||
@ -3038,17 +3050,6 @@ class Math_BigInteger {
|
|||||||
$max = new Math_BigInteger(0x7FFFFFFF);
|
$max = new Math_BigInteger(0x7FFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
$compare = $max->compare($min);
|
|
||||||
|
|
||||||
if (!$compare) {
|
|
||||||
return $min;
|
|
||||||
} else if ($compare < 0) {
|
|
||||||
// if $min is bigger then $max, swap $min and $max
|
|
||||||
$temp = $max;
|
|
||||||
$max = $min;
|
|
||||||
$min = $temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
$x = $this->random($min, $max);
|
$x = $this->random($min, $max);
|
||||||
|
|
||||||
$x->value = gmp_nextprime($x->value);
|
$x->value = gmp_nextprime($x->value);
|
||||||
@ -3066,50 +3067,78 @@ class Math_BigInteger {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$repeat1 = $repeat2 = array();
|
static $one, $two;
|
||||||
|
if (!isset($one)) {
|
||||||
$one = new Math_BigInteger(1);
|
$one = new Math_BigInteger(1);
|
||||||
$two = new Math_BigInteger(2);
|
$two = new Math_BigInteger(2);
|
||||||
|
}
|
||||||
|
|
||||||
$start = time();
|
$start = time();
|
||||||
|
|
||||||
do {
|
$x = $this->random($min, $max);
|
||||||
|
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) {
|
if ($timeout !== false && time() - $start > $timeout) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$x = $this->random($min, $max);
|
if ($x->isPrime()) {
|
||||||
if ($x->equals($two)) {
|
|
||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the number odd
|
$x = $x->add($two);
|
||||||
switch ( MATH_BIGINTEGER_MODE ) {
|
|
||||||
case MATH_BIGINTEGER_MODE_GMP:
|
|
||||||
gmp_setbit($x->value, 0);
|
|
||||||
break;
|
|
||||||
case MATH_BIGINTEGER_MODE_BCMATH:
|
|
||||||
if ($x->value[strlen($x->value) - 1] % 2 == 0) {
|
|
||||||
$x = $x->add($one);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$x->value[0] |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we've seen this number twice before, assume there are no prime numbers within the given range
|
if ($x->compare($max) > 0) {
|
||||||
if (in_array($x->value, $repeat1)) {
|
$x = $min->copy();
|
||||||
if (in_array($x->value, $repeat2)) {
|
if ($x->equals($two)) {
|
||||||
return false;
|
return $x;
|
||||||
} else {
|
|
||||||
$repeat2[] = $x->value;
|
|
||||||
}
|
}
|
||||||
} else {
|
$x->_make_odd();
|
||||||
$repeat1[] = $x->value;
|
|
||||||
}
|
}
|
||||||
} while (!$x->isPrime());
|
|
||||||
|
|
||||||
return $x;
|
if ($x->equals($initial_x)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the current number odd
|
||||||
|
*
|
||||||
|
* If the current number is odd it'll be unchanged. If it's even, one will be added to it.
|
||||||
|
*
|
||||||
|
* @see randomPrime()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _make_odd()
|
||||||
|
{
|
||||||
|
switch ( MATH_BIGINTEGER_MODE ) {
|
||||||
|
case MATH_BIGINTEGER_MODE_GMP:
|
||||||
|
gmp_setbit($this->value, 0);
|
||||||
|
break;
|
||||||
|
case MATH_BIGINTEGER_MODE_BCMATH:
|
||||||
|
if ($this->value[strlen($this->value) - 1] % 2 == 0) {
|
||||||
|
$this->value = bcadd($this->value, '1');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->value[0] |= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3152,7 +3181,7 @@ class Math_BigInteger {
|
|||||||
case MATH_BIGINTEGER_MODE_GMP:
|
case MATH_BIGINTEGER_MODE_GMP:
|
||||||
return gmp_prob_prime($this->value, $t) != 0;
|
return gmp_prob_prime($this->value, $t) != 0;
|
||||||
case MATH_BIGINTEGER_MODE_BCMATH:
|
case MATH_BIGINTEGER_MODE_BCMATH:
|
||||||
if ($this->value == '2') {
|
if ($this->value === '2') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($this->value[strlen($this->value) - 1] % 2 == 0) {
|
if ($this->value[strlen($this->value) - 1] % 2 == 0) {
|
||||||
@ -3229,7 +3258,7 @@ class Math_BigInteger {
|
|||||||
$s = 0;
|
$s = 0;
|
||||||
// if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
|
// if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
|
||||||
while ($r->value[strlen($r->value) - 1] % 2 == 0) {
|
while ($r->value[strlen($r->value) - 1] % 2 == 0) {
|
||||||
$r->value = bcdiv($r->value, 2, 0);
|
$r->value = bcdiv($r->value, '2', 0);
|
||||||
++$s;
|
++$s;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user