Psalm coverage for phpseclib3\Math\

Psalm coverage for phpseclib3\Math\
This commit is contained in:
Jack Worman 2022-02-21 07:43:51 -06:00 committed by terrafrost
parent 574953061a
commit 6f2db49696
16 changed files with 252 additions and 369 deletions

View File

@ -7,17 +7,14 @@
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedPsalmSuppress="true"
sealAllMethods="true"
errorBaseline="psalm_baseline.xml"
>
<projectFiles>
<directory name="../phpseclib/Common"/>
<!-- <directory name="../phpseclib/Crypt"/>-->
<directory name="../phpseclib/Exception"/>
<directory name="../phpseclib/File"/>
<!-- <directory name="../phpseclib/Math"/>-->
<directory name="../phpseclib/Net"/>
<directory name="../phpseclib/System"/>
<file name="../phpseclib/bootstrap.php"/>
<!-- <directory name="../tests"/>-->
<directory name="../phpseclib"/>
<ignoreFiles>
<directory name="../phpseclib/Crypt"/>
<directory name="../tests"/>
</ignoreFiles>
</projectFiles>
<issueHandlers>
<Trace>
@ -31,4 +28,4 @@
</errorLevel>
</UndefinedConstant>
</issueHandlers>
</psalm>
</psalm>

View File

@ -30,6 +30,7 @@
namespace phpseclib3\Math;
use phpseclib3\Exception\BadConfigurationException;
use phpseclib3\Math\BigInteger\Engines\Engine;
/**
* Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
@ -44,21 +45,14 @@ class BigInteger
/**
* Main Engine
*
* @var string
* @var class-string<Engine>
*/
private static $mainEngine;
/**
* Modular Exponentiation Engine
*
* @var string
*/
private static $modexpEngine;
/**
* Selected Engines
*
* @var array
* @var list<string>
*/
private static $engines;
@ -93,9 +87,10 @@ class BigInteger
* Throws an exception if the type is invalid
*
* @param string $main
* @param array $modexps optional
* @param list<string> $modexps optional
* @return void
*/
public static function setEngine($main, $modexps = ['DefaultEngine'])
public static function setEngine($main, array $modexps = ['DefaultEngine'])
{
self::$engines = [];
@ -106,6 +101,7 @@ class BigInteger
if (!$fqmain::isValidEngine()) {
throw new BadConfigurationException("$main is not setup correctly on this system");
}
/** @var class-string<Engine> $fqmain */
self::$mainEngine = $fqmain;
if (!in_array('Default', $modexps)) {
@ -126,8 +122,6 @@ class BigInteger
throw new BadConfigurationException("No valid modular exponentiation engine found for $main");
}
self::$modexpEngine = $modexp;
self::$engines = [$main, $modexp];
}
@ -173,7 +167,6 @@ class BigInteger
*
* @param string|int|BigInteger\Engines\Engine $x Base-10 number or base-$base number if $base set.
* @param int $base
* @return BigInteger
*/
public function __construct($x = 0, $base = 10)
{
@ -418,7 +411,7 @@ class BigInteger
* __serialize() / __unserialize() were introduced in PHP 7.4:
* https://wiki.php.net/rfc/custom_object_serialization
*
* @return string
* @return array
*/
public function __sleep()
{

View File

@ -44,48 +44,6 @@ class BCMath extends Engine
*/
const ENGINE_DIR = 'BCMath';
/**
* Modular Exponentiation Engine
*
* @var string
*/
protected static $modexpEngine;
/**
* Engine Validity Flag
*
* @var bool
*/
protected static $isValidEngine;
/**
* BigInteger(0)
*
* @var \phpseclib3\Math\BigInteger\Engines\BCMath
*/
protected static $zero;
/**
* BigInteger(1)
*
* @var \phpseclib3\Math\BigInteger\Engines\BCMath
*/
protected static $one;
/**
* BigInteger(2)
*
* @var \phpseclib3\Math\BigInteger\Engines\BCMath
*/
protected static $two;
/**
* Primes > 2 and < 1000
*
* @var array
*/
protected static $primes;
/**
* Test for engine validity
*
@ -102,15 +60,14 @@ class BCMath extends Engine
*
* @param mixed $x integer Base-10 number or base-$base number if $base set.
* @param int $base
* @return \phpseclib3\Math\BigInteger\Engines\BCMath
* @see parent::__construct()
*/
public function __construct($x = 0, $base = 10)
{
if (!isset(self::$isValidEngine)) {
self::$isValidEngine = self::isValidEngine();
if (!isset(static::$isValidEngine[static::class])) {
static::$isValidEngine[static::class] = self::isValidEngine();
}
if (!self::$isValidEngine) {
if (!static::$isValidEngine[static::class]) {
throw new BadConfigurationException('BCMath is not setup correctly on this system');
}
@ -258,7 +215,7 @@ class BCMath extends Engine
* and the divisor (basically, the "common residue" is the first positive modulo).
*
* @param BCMath $y
* @return BCMath
* @return array{static, static}
*/
public function divide(BCMath $y)
{
@ -297,7 +254,7 @@ class BCMath extends Engine
* {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
*
* @param BCMath $n
* @return BCMath
* @return array{gcd: static, x: static, y: static}
*/
public function extendedGCD(BCMath $n)
{
@ -503,7 +460,7 @@ class BCMath extends Engine
protected function powModInner(BCMath $e, BCMath $n)
{
try {
$class = self::$modexpEngine;
$class = static::$modexpEngine[static::class];
return $class::powModHelper($this, $e, $n, static::class);
} catch (\Exception $err) {
return BCMath\DefaultEngine::powModHelper($this, $e, $n, static::class);
@ -595,7 +552,7 @@ class BCMath extends Engine
$value = $this->value;
foreach (self::$primes as $prime) {
foreach (self::PRIMES as $prime) {
$r = bcmod($this->value, $prime);
if ($r == '0') {
return $this->value == $prime;
@ -618,7 +575,7 @@ class BCMath extends Engine
{
$r_value = &$r->value;
$s = 0;
// if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals(static::$one) check earlier
// if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals(static::$one[static::class]) check earlier
while ($r_value[strlen($r_value) - 1] % 2 == 0) {
$r_value = bcdiv($r_value, '2', 0);
++$s;
@ -685,13 +642,13 @@ class BCMath extends Engine
protected static function setBitmask($bits)
{
$temp = parent::setBitmask($bits);
return $temp->add(static::$one);
return $temp->add(static::$one[static::class]);
}
/**
* Is Odd?
*
* @return boolean
* @return bool
*/
public function isOdd()
{
@ -701,7 +658,7 @@ class BCMath extends Engine
/**
* Tests if a bit is set
*
* @return boolean
* @return bool
*/
public function testBit($x)
{

View File

@ -78,7 +78,7 @@ abstract class EvalBarrett extends Base
$u = "'$u'";
$m1 = "'$m1'";
$code .= '
$code = '
$lsd = substr($n, -' . $cutoff . ');
$msd = substr($n, 0, -' . $cutoff . ');

View File

@ -30,10 +30,59 @@ use phpseclib3\Math\BigInteger;
*/
abstract class Engine
{
/* final protected */ const PRIMES = [
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997,
];
/**
* BigInteger(0)
*
* @var array<class-string<static>, static>
*/
protected static $zero = [];
/**
* BigInteger(1)
*
* @var array<class-string<static>, static>
*/
protected static $one = [];
/**
* BigInteger(2)
*
* @var array<class-string<static>, static>
*/
protected static $two = [];
/**
* Modular Exponentiation Engine
*
* @var array<class-string<static>, class-string<static>>
*/
protected static $modexpEngine;
/**
* Engine Validity Flag
*
* @var array<class-string<static>, bool>
*/
protected static $isValidEngine;
/**
* Holds the BigInteger's value
*
* @var mixed
* @var \GMP|string|array|int
*/
protected $value;
@ -48,6 +97,7 @@ abstract class Engine
* Precision
*
* @see static::setPrecision()
* @var int
*/
protected $precision = -1;
@ -55,6 +105,7 @@ abstract class Engine
* Precision Bitmask
*
* @see static::setPrecision()
* @var static|false
*/
protected $bitmask = false;
@ -77,28 +128,16 @@ abstract class Engine
/**
* Default constructor
*
* @param mixed $x integer Base-10 number or base-$base number if $base set.
* @param int|numeric-string $x integer Base-10 number or base-$base number if $base set.
* @param int $base
*/
public function __construct($x, $base)
public function __construct($x = 0, $base = 10)
{
if (!isset(static::$primes)) {
static::$primes = [
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997
];
static::$zero = new static(0);
static::$one = new static(1);
static::$two = new static(2);
if (!array_key_exists(static::class, static::$zero)) {
static::$zero[static::class] = null; // Placeholder to prevent infinite loop.
static::$zero[static::class] = new static(0);
static::$one[static::class] = new static(1);
static::$two[static::class] = new static(2);
}
// '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
@ -118,7 +157,7 @@ abstract class Engine
$this->is_negative = false;
}
static::initialize($base);
$this->initialize($base);
if ($this->is_negative) {
$temp = $this->add(new static('-1'));
@ -141,7 +180,7 @@ abstract class Engine
}
$this->value = $x;
static::initialize($base);
$this->initialize($base);
if ($is_negative) {
$temp = $this->add(new static('-1'));
@ -157,7 +196,7 @@ abstract class Engine
if (!strlen($this->value) || $this->value == '-') {
$this->value = '0';
}
static::initialize($base);
$this->initialize($base);
break;
case -2:
case 2:
@ -185,7 +224,7 @@ abstract class Engine
*
* Throws an exception if the type is invalid
*
* @param string $engine
* @param class-string<Engine> $engine
*/
public static function setModExpEngine($engine)
{
@ -196,7 +235,7 @@ abstract class Engine
if (!$fqengine::isValidEngine()) {
throw new BadConfigurationException("$engine is not setup correctly on this system");
}
static::$modexpEngine = $fqengine;
static::$modexpEngine[static::class] = $fqengine;
}
/**
@ -268,15 +307,15 @@ abstract class Engine
*
* {@internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.}
*
* @param \phpseclib3\Math\BigInteger\Engines\Engine $n
* @return \phpseclib3\Math\BigInteger\Engines\Engine|false
* @param Engine $n
* @return static|false
*/
protected function modInverseHelper(Engine $n)
{
// $x mod -$n == $x mod $n.
$n = $n->abs();
if ($this->compare(static::$zero) < 0) {
if ($this->compare(static::$zero[static::class]) < 0) {
$temp = $this->abs();
$temp = $temp->modInverse($n);
return $this->normalize($n->subtract($temp));
@ -284,17 +323,17 @@ abstract class Engine
extract($this->extendedGCD($n));
/**
* @var BigInteger $gcd
* @var BigInteger $x
* @var Engine $gcd
* @var Engine $x
*/
if (!$gcd->equals(static::$one)) {
if (!$gcd->equals(static::$one[static::class])) {
return false;
}
$x = $x->compare(static::$zero) < 0 ? $x->add($n) : $x;
$x = $x->compare(static::$zero[static::class]) < 0 ? $x->add($n) : $x;
return $this->compare(static::$zero) < 0 ? $this->normalize($n->subtract($x)) : $this->normalize($x);
return $this->compare(static::$zero[static::class]) < 0 ? $this->normalize($n->subtract($x)) : $this->normalize($x);
}
/**
@ -302,7 +341,7 @@ abstract class Engine
*
* Will be called, automatically, when serialize() is called on a BigInteger object.
*
* @return string
* @return array
*/
public function __sleep()
{
@ -318,6 +357,8 @@ abstract class Engine
* Serialize
*
* Will be called, automatically, when unserialize() is called on a BigInteger object.
*
* @return void
*/
public function __wakeup()
{
@ -344,6 +385,8 @@ abstract class Engine
* __debugInfo() magic method
*
* Will be called, automatically, when print_r() or var_dump() are called
*
* @return array
*/
public function __debugInfo()
{
@ -390,7 +433,7 @@ abstract class Engine
/**
* Set Bitmask
* @return Engine
* @return static
* @param int $bits
* @see self::setPrecision()
*/
@ -410,7 +453,7 @@ abstract class Engine
// (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
$temp = $this->toBytes();
if ($temp == '') {
return $this->normalize(static::$zero);
return $this->normalize(static::$zero[static::class]);
}
$pre_msb = decbin(ord($temp[0]));
$temp = ~$temp;
@ -444,7 +487,7 @@ abstract class Engine
*
* @param string $x
* @param int $shift
* @return string
* @return void
*/
protected static function base256_lshift(&$x, $shift)
{
@ -471,7 +514,7 @@ abstract class Engine
* Instead of the top x bits being dropped they're appended to the shifted bit string.
*
* @param int $shift
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @return Engine
*/
public function bitwise_leftRotate($shift)
{
@ -515,7 +558,7 @@ abstract class Engine
* Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
*
* @param int $shift
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @return Engine
*/
public function bitwise_rightRotate($shift)
{
@ -526,7 +569,7 @@ abstract class Engine
* Returns the smallest and largest n-bit number
*
* @param int $bits
* @return \phpseclib3\Math\BigInteger\Engines\Engine[]
* @return array{min: static, max: static}
*/
public static function minMaxBits($bits)
{
@ -571,7 +614,7 @@ abstract class Engine
*
* @param Engine $e
* @param Engine $n
* @return bool|Engine
* @return static|false
*/
protected function powModOuter(Engine $e, Engine $n)
{
@ -599,11 +642,12 @@ abstract class Engine
* however, this function performs a modular reduction after every multiplication and squaring operation.
* As such, this function has the same preconditions that the reductions being used do.
*
* @param \phpseclib3\Math\BigInteger\Engines\Engine $x
* @param \phpseclib3\Math\BigInteger\Engines\Engine $e
* @param \phpseclib3\Math\BigInteger\Engines\Engine $n
* @param string $class
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @template T of Engine
* @param Engine $x
* @param Engine $e
* @param Engine $n
* @param class-string<T> $class
* @return T
*/
protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class)
{
@ -674,7 +718,7 @@ abstract class Engine
* Bit length is equal to $size
*
* @param int $size
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @return Engine
*/
public static function random($size)
{
@ -692,14 +736,14 @@ abstract class Engine
* Bit length is equal to $size
*
* @param int $size
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @return Engine
*/
public static function randomPrime($size)
{
extract(static::minMaxBits($size));
/**
* @var BigInteger $min
* @var BigInteger $max
* @var static $min
* @var static $max
*/
return static::randomRangePrime($min, $max);
}
@ -709,7 +753,7 @@ abstract class Engine
*
* @param Engine $min
* @param Engine $max
* @return bool|Engine
* @return static|false
*/
protected static function randomRangePrimeOuter(Engine $min, Engine $max)
{
@ -755,11 +799,11 @@ abstract class Engine
$min = $temp;
}
if (!isset(static::$one)) {
static::$one = new static(1);
if (!isset(static::$one[static::class])) {
static::$one[static::class] = new static(1);
}
$max = $max->subtract($min->subtract(static::$one));
$max = $max->subtract($min->subtract(static::$one[static::class]));
$size = strlen(ltrim($max->toBytes(), chr(0)));
@ -804,12 +848,12 @@ abstract class Engine
* @param Engine $x
* @param Engine $min
* @param Engine $max
* @return bool|Engine
* @return static|false
*/
protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max)
{
if (!isset(static::$two)) {
static::$two = new static('2');
if (!isset(static::$two[static::class])) {
static::$two[static::class] = new static('2');
}
$x->make_odd();
@ -829,11 +873,11 @@ abstract class Engine
return $x;
}
$x = $x->add(static::$two);
$x = $x->add(static::$two[static::class]);
if ($x->compare($max) > 0) {
$x = clone $min;
if ($x->equals(static::$two)) {
if ($x->equals(static::$two[static::class])) {
return $x;
}
$x->make_odd();
@ -856,7 +900,7 @@ abstract class Engine
// see HAC 4.49 "Note (controlling the error probability)"
// @codingStandardsIgnoreStart
if ($length >= 163) { $t = 2; } // floor(1300 / 8)
if ($length >= 163) $t = 2; // floor(1300 / 8)
else if ($length >= 106) { $t = 3; } // floor( 850 / 8)
else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8)
else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8)
@ -889,20 +933,20 @@ abstract class Engine
}
$n = clone $this;
$n_1 = $n->subtract(static::$one);
$n_2 = $n->subtract(static::$two);
$n_1 = $n->subtract(static::$one[static::class]);
$n_2 = $n->subtract(static::$two[static::class]);
$r = clone $n_1;
$s = static::scan1divide($r);
for ($i = 0; $i < $t; ++$i) {
$a = static::randomRange(static::$two, $n_2);
$a = static::randomRange(static::$two[static::class], $n_2);
$y = $a->modPow($r, $n);
if (!$y->equals(static::$one) && !$y->equals($n_1)) {
if (!$y->equals(static::$one[static::class]) && !$y->equals($n_1)) {
for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) {
$y = $y->modPow(static::$two, $n);
if ($y->equals(static::$one)) {
$y = $y->modPow(static::$two[static::class], $n);
if ($y->equals(static::$one[static::class])) {
return false;
}
}
@ -938,18 +982,18 @@ abstract class Engine
* Performs a few preliminary checks on root
*
* @param int $n
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @return Engine
*/
protected function rootHelper($n)
{
if ($n < 1) {
return clone static::$zero;
return clone static::$zero[static::class];
} // we want positive exponents
if ($this->compare(static::$one) < 0) {
return clone static::$zero;
if ($this->compare(static::$one[static::class]) < 0) {
return clone static::$zero[static::class];
} // we want positive numbers
if ($this->compare(static::$two) < 0) {
return clone static::$one;
if ($this->compare(static::$two[static::class]) < 0) {
return clone static::$one[static::class];
} // n-th root of 1 or 2 is 1
return $this->rootInner($n);
@ -963,17 +1007,17 @@ abstract class Engine
* {@internal This function is based off of {@link http://mathforum.org/library/drmath/view/52605.html this page} and {@link http://stackoverflow.com/questions/11242920/calculating-nth-root-with-bcmath-in-php this stackoverflow question}.}
*
* @param int $n
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @return Engine
*/
protected function rootInner($n)
{
$n = new static($n);
// g is our guess number
$g = static::$two;
$g = static::$two[static::class];
// while (g^n < num) g=g*2
while ($g->pow($n)->compare($this) < 0) {
$g = $g->multiply(static::$two);
$g = $g->multiply(static::$two[static::class]);
}
// if (g^n==num) num is a power of 2, we're lucky, end of job
// == 0 bccomp(bcpow($g, $n), $n->value)==0
@ -984,15 +1028,15 @@ abstract class Engine
// if we're here num wasn't a power of 2 :(
$og = $g; // og means original guess and here is our upper bound
$g = $g->divide(static::$two)[0]; // g is set to be our lower bound
$step = $og->subtract($g)->divide(static::$two)[0]; // step is the half of upper bound - lower bound
$g = $g->divide(static::$two[static::class])[0]; // g is set to be our lower bound
$step = $og->subtract($g)->divide(static::$two[static::class])[0]; // step is the half of upper bound - lower bound
$g = $g->add($step); // we start at lower bound + step , basically in the middle of our interval
// while step>1
while ($step->compare(static::$one) == 1) {
while ($step->compare(static::$one[static::class]) == 1) {
$guess = $g->pow($n);
$step = $step->divide(static::$two)[0];
$step = $step->divide(static::$two[static::class])[0];
$comp = $guess->compare($this); // compare our guess with real number
switch ($comp) {
case -1: // if guess is lower we add the new step
@ -1076,9 +1120,9 @@ abstract class Engine
{
$class = static::class;
$fqengine = !method_exists(static::$modexpEngine, 'reduce') ?
$fqengine = !method_exists(static::$modexpEngine[static::class], 'reduce') ?
'\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\DefaultEngine' :
static::$modexpEngine;
static::$modexpEngine[static::class];
if (method_exists($fqengine, 'generateCustomReduction')) {
$func = $fqengine::generateCustomReduction($this, static::class);
return eval('return function(' . static::class . ' $x) use ($func, $class) {
@ -1099,10 +1143,9 @@ abstract class Engine
* Calculates the greatest common divisor and Bezout's identity.
*
* @param Engine $n
* @param Engine $stop (optional)
* @return Engine
* @return array{gcd: Engine, x: Engine, y: Engine}
*/
protected function extendedGCDHelper(Engine $n, Engine $stop = null)
protected function extendedGCDHelper(Engine $n)
{
$u = clone $this;
$v = clone $n;
@ -1144,7 +1187,7 @@ abstract class Engine
* Splits BigInteger's into chunks of $split bits
*
* @param int $split
* @return \phpseclib3\Math\BigInteger\Engines\Engine[]
* @return Engine[]
*/
public function bitwise_split($split)
{
@ -1152,12 +1195,12 @@ abstract class Engine
throw new \RuntimeException('Offset must be greater than 1');
}
$mask = static::$one->bitwise_leftShift($split)->subtract(static::$one);
$mask = static::$one[static::class]->bitwise_leftShift($split)->subtract(static::$one[static::class]);
$num = clone $this;
$vals = [];
while (!$num->equals(static::$zero)) {
while (!$num->equals(static::$zero[static::class])) {
$vals[] = $num->bitwise_and($mask);
$num = $num->bitwise_rightShift($split);
}

View File

@ -43,50 +43,6 @@ class GMP extends Engine
*/
const ENGINE_DIR = 'GMP';
/**
* Modular Exponentiation Engine
*
* @var string
*/
protected static $modexpEngine;
/**
* Engine Validity Flag
*
* @var bool
*/
protected static $isValidEngine;
/**
* BigInteger(0)
*
* @var \phpseclib3\Math\BigInteger\Engines\GMP
*/
protected static $zero;
/**
* BigInteger(1)
*
* @var \phpseclib3\Math\BigInteger\Engines\GMP
*/
protected static $one;
/**
* BigInteger(2)
*
* @var \phpseclib3\Math\BigInteger\Engines\GMP
*/
protected static $two;
/**
* Primes > 2 and < 1000
*
* Unused for GMP Engine
*
* @var mixed
*/
protected static $primes;
/**
* Test for engine validity
*
@ -103,15 +59,14 @@ class GMP extends Engine
*
* @param mixed $x integer Base-10 number or base-$base number if $base set.
* @param int $base
* @return \phpseclib3\Math\BigInteger\Engines\GMP
* @see parent::__construct()
*/
public function __construct($x = 0, $base = 10)
{
if (!isset(self::$isValidEngine)) {
self::$isValidEngine = self::isValidEngine();
if (!isset(static::$isValidEngine[static::class])) {
static::$isValidEngine[static::class] = self::isValidEngine();
}
if (!self::$isValidEngine) {
if (!static::$isValidEngine[static::class]) {
throw new BadConfigurationException('GMP is not setup correctly on this system');
}
@ -259,7 +214,7 @@ class GMP extends Engine
* and the divisor (basically, the "common residue" is the first positive modulo).
*
* @param GMP $y
* @return GMP
* @return array{GMP, GMP}
*/
public function divide(GMP $y)
{
@ -497,7 +452,7 @@ class GMP extends Engine
*/
protected function powModInner(GMP $e, GMP $n)
{
$class = self::$modexpEngine;
$class = static::$modexpEngine[static::class];
return $class::powModHelper($this, $e, $n);
}

View File

@ -81,10 +81,10 @@ abstract class PHP extends Engine
*/
public function __construct($x = 0, $base = 10)
{
if (!isset(static::$isValidEngine)) {
static::$isValidEngine = static::isValidEngine();
if (!isset(static::$isValidEngine[static::class])) {
static::$isValidEngine[static::class] = static::isValidEngine();
}
if (!static::$isValidEngine) {
if (!static::$isValidEngine[static::class]) {
throw new BadConfigurationException(static::class . ' is not setup correctly on this system');
}
@ -530,8 +530,7 @@ abstract class PHP extends Engine
* same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
* and the divisor (basically, the "common residue" is the first positive modulo).
*
* @param \phpseclib3\Math\BigInteger\engines\PHP $y
* @return array
* @return array{static, static}
* @internal This function is based off of
* {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
*/
@ -561,7 +560,7 @@ abstract class PHP extends Engine
$temp = new static();
$temp->value = [1];
$temp->is_negative = $x_sign != $y_sign;
return [$this->normalize($temp), $this->normalize(static::$zero)];
return [$this->normalize($temp), $this->normalize(static::$zero[static::class])];
}
if ($diff < 0) {
@ -569,7 +568,7 @@ abstract class PHP extends Engine
if ($x_sign) {
$x = $y->subtract($x);
}
return [$this->normalize(static::$zero), $this->normalize($x)];
return [$this->normalize(static::$zero[static::class]), $this->normalize($x)];
}
// normalize $x and $y as described in HAC 14.23 / 14.24
@ -658,7 +657,7 @@ abstract class PHP extends Engine
$x = $x->subtract($temp);
if ($x->compare(static::$zero) < 0) {
if ($x->compare(static::$zero[static::class]) < 0) {
$temp_value = array_merge($adjust, $y_value);
$x = $x->add($temp);
@ -724,14 +723,15 @@ abstract class PHP extends Engine
}
// static::BASE === 31
/** @var int */
return ($x - ($x % $y)) / $y;
}
/*
/**
* Convert an array / boolean to a PHP BigInteger object
*
* @param array $arr
* @return \phpseclib3\Math\BigInteger\Engines\PHP
* @return static
*/
protected function convertToObj(array $arr)
{
@ -748,7 +748,7 @@ abstract class PHP extends Engine
* Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
*
* @param PHP $result
* @return PHP
* @return static
*/
protected function normalize(PHP $result)
{
@ -776,7 +776,7 @@ abstract class PHP extends Engine
return $result;
}
/*
/**
* Compares two numbers.
*
* @param array $x_value
@ -829,8 +829,8 @@ abstract class PHP extends Engine
*
* Removes leading zeros
*
* @param array $value
* @return PHP
* @param list<static> $value
* @return list<static>
*/
protected static function trim(array $value)
{
@ -983,7 +983,7 @@ abstract class PHP extends Engine
protected function powModInner(PHP $e, PHP $n)
{
try {
$class = static::$modexpEngine;
$class = static::$modexpEngine[static::class];
return $class::powModHelper($this, $e, $n, static::class);
} catch (\Exception $err) {
return PHP\DefaultEngine::powModHelper($this, $e, $n, static::class);
@ -993,8 +993,8 @@ abstract class PHP extends Engine
/**
* Performs squaring
*
* @param array $x
* @return array
* @param list<static> $x
* @return list<static>
*/
protected static function square(array $x)
{
@ -1109,7 +1109,7 @@ abstract class PHP extends Engine
}
$value = $this->value;
foreach (static::$primes as $prime) {
foreach (static::PRIMES as $prime) {
list(, $r) = self::divide_digit($value, $prime);
if (!$r) {
return count($value) == 1 && $value[0] == $prime;
@ -1152,14 +1152,14 @@ abstract class PHP extends Engine
*/
protected function powHelper(PHP $n)
{
if ($n->compare(static::$zero) == 0) {
if ($n->compare(static::$zero[static::class]) == 0) {
return new static(1);
} // n^0 = 1
$temp = clone $this;
while (!$n->equals(static::$one)) {
while (!$n->equals(static::$one[static::class])) {
$temp = $temp->multiply($this);
$n = $n->subtract(static::$one);
$n = $n->subtract(static::$one[static::class]);
}
return $temp;
@ -1168,7 +1168,7 @@ abstract class PHP extends Engine
/**
* Is Odd?
*
* @return boolean
* @return bool
*/
public function isOdd()
{
@ -1178,11 +1178,11 @@ abstract class PHP extends Engine
/**
* Tests if a bit is set
*
* @return boolean
* @return bool
*/
public function testBit($x)
{
$digit = floor($x / static::BASE);
$digit = (int) floor($x / static::BASE);
$bit = $x % static::BASE;
if (!isset($this->value[$digit])) {
@ -1195,7 +1195,7 @@ abstract class PHP extends Engine
/**
* Is Negative?
*
* @return boolean
* @return bool
*/
public function isNegative()
{
@ -1207,7 +1207,7 @@ abstract class PHP extends Engine
*
* Given $k, returns -$k
*
* @return BigInteger
* @return static
*/
public function negate()
{
@ -1223,7 +1223,7 @@ abstract class PHP extends Engine
* Splits BigInteger's into chunks of $split bits
*
* @param int $split
* @return \phpseclib3\Math\BigInteger\Engines\PHP[]
* @return list<static>
*/
public function bitwise_split($split)
{
@ -1290,7 +1290,7 @@ abstract class PHP extends Engine
* Bitwise Split where $split < static::BASE
*
* @param int $split
* @return \phpseclib3\Math\BigInteger\Engines\PHP[]
* @return list<int>
*/
private function bitwise_small_split($split)
{

View File

@ -41,11 +41,12 @@ abstract class Montgomery extends Base
/**
* Performs modular exponentiation.
*
* @param \phpseclib3\Math\BigInteger\Engines\Engine $x
* @param \phpseclib3\Math\BigInteger\Engines\Engine $e
* @param \phpseclib3\Math\BigInteger\Engines\Engine $n
* @param string $class
* @return \phpseclib3\Math\BigInteger\Engines\Engine
* @template T of Engine
* @param Engine $x
* @param Engine $e
* @param Engine $n
* @param class-string<T> $class
* @return T
*/
protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class)
{

View File

@ -469,7 +469,7 @@ abstract class EvalBarrett extends Base
private static function float2string($num)
{
if (!is_float($num)) {
return $num;
return (string) $num;
}
if ($num < 0) {

View File

@ -15,6 +15,8 @@
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;
use phpseclib3\Math\BigInteger\Engines\PHP;
/**
* PHP Montgomery Modular Exponentiation Engine with interleaved multiplication
*
@ -36,7 +38,7 @@ abstract class MontgomeryMult extends Montgomery
* @param array $x
* @param array $y
* @param array $m
* @param string $class
* @param class-string<PHP> $class
* @return array
*/
public static function multiplyReduce(array $x, array $y, array $m, $class)

View File

@ -44,49 +44,6 @@ class PHP32 extends PHP
*/
const MAX10LEN = 7;
const MAX_DIGIT2 = 4503599627370496;
/**#@-*/
/**
* Modular Exponentiation Engine
*
* @var string
*/
protected static $modexpEngine;
/**
* Engine Validity Flag
*
* @var bool
*/
protected static $isValidEngine;
/**
* Primes > 2 and < 1000
*
* @var array
*/
protected static $primes;
/**
* BigInteger(0)
*
* @var \phpseclib3\Math\BigInteger\Engines\PHP32
*/
protected static $zero;
/**
* BigInteger(1)
*
* @var \phpseclib3\Math\BigInteger\Engines\PHP32
*/
protected static $one;
/**
* BigInteger(2)
*
* @var \phpseclib3\Math\BigInteger\Engines\PHP32
*/
protected static $two;
/**
* Initialize a PHP32 BigInteger Engine instance
@ -197,7 +154,7 @@ class PHP32 extends PHP
* and the divisor (basically, the "common residue" is the first positive modulo).
*
* @param PHP32 $y
* @return PHP32
* @return array{PHP32, PHP32}
*/
public function divide(PHP32 $y)
{

View File

@ -44,49 +44,6 @@ class PHP64 extends PHP
*/
const MAX10LEN = 9;
const MAX_DIGIT2 = 4611686018427387904;
/**#@-*/
/**
* Modular Exponentiation Engine
*
* @var string
*/
protected static $modexpEngine;
/**
* Engine Validity Flag
*
* @var bool
*/
protected static $isValidEngine;
/**
* Primes > 2 and < 1000
*
* @var array
*/
protected static $primes;
/**
* BigInteger(0)
*
* @var \phpseclib3\Math\BigInteger\Engines\PHP64
*/
protected static $zero;
/**
* BigInteger(1)
*
* @var \phpseclib3\Math\BigInteger\Engines\PHP64
*/
protected static $one;
/**
* BigInteger(2)
*
* @var \phpseclib3\Math\BigInteger\Engines\PHP64
*/
protected static $two;
/**
* Initialize a PHP64 BigInteger Engine instance
@ -201,7 +158,7 @@ class PHP64 extends PHP
* and the divisor (basically, the "common residue" is the first positive modulo).
*
* @param PHP64 $y
* @return PHP64
* @return array{PHP64, PHP64}
*/
public function divide(PHP64 $y)
{
@ -334,7 +291,7 @@ class PHP64 extends PHP
*
* @param PHP64 $e
* @param PHP64 $n
* @return PHP64
* @return PHP64|false
*/
public function powMod(PHP64 $e, PHP64 $n)
{

View File

@ -43,6 +43,9 @@ class BinaryField extends FiniteField
*/
protected $instanceID;
/** @var BigInteger */
private $randomMax;
/**
* Default constructor
*/
@ -113,7 +116,7 @@ class BinaryField extends FiniteField
* Returns an instance of a dynamically generated PrimeFieldInteger class
*
* @param string $num
* @return object
* @return Integer
*/
public function newInteger($num)
{
@ -123,7 +126,7 @@ class BinaryField extends FiniteField
/**
* Returns an integer on the finite field between one and the prime modulo
*
* @return object
* @return Integer
*/
public function randomInteger()
{
@ -138,7 +141,7 @@ class BinaryField extends FiniteField
/**
* Returns the length of the modulo in bytes
*
* @return integer
* @return int
*/
public function getLengthInBytes()
{
@ -148,7 +151,7 @@ class BinaryField extends FiniteField
/**
* Returns the length of the modulo in bits
*
* @return integer
* @return int
*/
public function getLength()
{

View File

@ -53,7 +53,7 @@ class Integer extends Base
/**
* Holds the PrimeField's modulo
*
* @var string[]
* @var array<int, string>
*/
protected static $modulo;
@ -80,6 +80,8 @@ class Integer extends Base
/**
* Set the modulo for a given instance
* @param int $instanceID
* @param string $modulo
*/
public static function setModulo($instanceID, $modulo)
{
@ -450,7 +452,7 @@ class Integer extends Base
/**
* Returns the modulo
*
* @return integer
* @return string
*/
public static function getModulo($instanceID)
{

View File

@ -61,8 +61,10 @@ class PrimeField extends FiniteField
/**
* Use a custom defined modular reduction function
*
* @return void
*/
public function setReduction(callable $func)
public function setReduction(\Closure $func)
{
$this->reduce = $func->bindTo($this, $this);
}
@ -70,7 +72,7 @@ class PrimeField extends FiniteField
/**
* Returns an instance of a dynamically generated PrimeFieldInteger class
*
* @return object
* @return Integer
*/
public function newInteger(BigInteger $num)
{
@ -80,7 +82,7 @@ class PrimeField extends FiniteField
/**
* Returns an integer on the finite field between one and the prime modulo
*
* @return object
* @return Integer
*/
public function randomInteger()
{
@ -95,7 +97,7 @@ class PrimeField extends FiniteField
/**
* Returns the length of the modulo in bytes
*
* @return integer
* @return int
*/
public function getLengthInBytes()
{
@ -105,7 +107,7 @@ class PrimeField extends FiniteField
/**
* Returns the length of the modulo in bits
*
* @return integer
* @return int
*/
public function getLength()
{

View File

@ -30,7 +30,7 @@ class Integer extends Base
/**
* Holds the PrimeField's value
*
* @var \phpseclib3\Math\BigInteger
* @var BigInteger
*/
protected $value;
@ -44,32 +44,34 @@ class Integer extends Base
/**
* Holds the PrimeField's modulo
*
* @var \phpseclib3\Math\BigInteger
* @var array<int, BigInteger>
*/
protected static $modulo;
/**
* Holds a pre-generated function to perform modulo reductions
*
* @var Callable
* @var array<int, callable(BigInteger):BigInteger>
*/
protected static $reduce;
/**
* Zero
*
* @var \phpseclib3\Math\BigInteger
* @var BigInteger
*/
protected static $zero;
/**
* Default constructor
*
* @param int $instanceID
*/
public function __construct($instanceID, BigInteger $num = null)
{
$this->instanceID = $instanceID;
if (!isset($num)) {
$this->value = clone static::$zero;
$this->value = clone static::$zero[static::class];
} else {
$reduce = static::$reduce[$instanceID];
$this->value = $reduce($num);
@ -78,6 +80,9 @@ class Integer extends Base
/**
* Set the modulo for a given instance
*
* @param int $instanceID
* @return void
*/
public static function setModulo($instanceID, BigInteger $modulo)
{
@ -86,12 +91,15 @@ class Integer extends Base
/**
* Set the modulo for a given instance
*
* @param int $instanceID
* @return void
*/
public static function setRecurringModuloFunction($instanceID, callable $function)
{
static::$reduce[$instanceID] = $function;
if (!isset(static::$zero)) {
static::$zero = new BigInteger();
if (!isset(static::$zero[static::class])) {
static::$zero[static::class] = new BigInteger();
}
}
@ -107,7 +115,8 @@ class Integer extends Base
/**
* Returns the modulo
*
* @return integer
* @param int $instanceID
* @return BigInteger
*/
public static function getModulo($instanceID)
{
@ -118,6 +127,8 @@ class Integer extends Base
* Tests a parameter to see if it's of the right instance
*
* Throws an exception if the incorrect class is being utilized
*
* @return void
*/
public static function checkInstance(self $x, self $y)
{
@ -278,7 +289,7 @@ class Integer extends Base
/**
* Is Odd?
*
* @return boolean
* @return bool
*/
public function isOdd()
{
@ -291,7 +302,7 @@ class Integer extends Base
* A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo
* so 0-12 is the same thing as modulo-12
*
* @return object
* @return static
*/
public function negate()
{
@ -339,7 +350,7 @@ class Integer extends Base
* Returns the w-ary non-adjacent form (wNAF)
*
* @param int $w optional
* @return int[]
* @return array<int, int>
*/
public function getNAF($w = 1)
{
@ -352,20 +363,21 @@ class Integer extends Base
$d_i = [];
$i = 0;
while ($d->compare(static::$zero) > 0) {
while ($d->compare(static::$zero[static::class]) > 0) {
if ($d->isOdd()) {
// start mods
$d_i[$i] = $d->testBit($w - 1) ?
$bigInteger = $d->testBit($w - 1) ?
$d->bitwise_and($mask)->subtract($sub) :
//$sub->subtract($d->bitwise_and($mask)) :
$d->bitwise_and($mask);
// end mods
$d = $d->subtract($d_i[$i]);
$d_i[$i] = (int) $d_i[$i]->toString();
$d = $d->subtract($bigInteger);
$d_i[$i] = (int) $bigInteger->toString();
} else {
$d_i[$i] = 0;
}
$shift = !$d->equals(static::$zero) && $d->bitwise_and($mask)->equals(static::$zero) ? $w : 1; // $w or $w + 1?
$shift = !$d->equals(static::$zero[static::class]) && $d->bitwise_and($mask)->equals(static::$zero[static::class]) ? $w : 1; // $w or $w + 1?
$d = $d->bitwise_rightShift($shift);
while (--$shift > 0) {
$d_i[++$i] = 0;
@ -379,7 +391,7 @@ class Integer extends Base
/**
* Converts an Integer to a BigInteger
*
* @return string
* @return BigInteger
*/
public function toBigInteger()
{
@ -390,6 +402,7 @@ class Integer extends Base
* __toString() magic method
*
* @access public
* @return string
*/
public function __toString()
{
@ -400,6 +413,7 @@ class Integer extends Base
* __debugInfo() magic method
*
* @access public
* @return array
*/
public function __debugInfo()
{