File modules/phpseclib/Math/BigInteger.class.php

Last commit: Sat Oct 31 00:43:29 2020 +0100	Jan Dankert	New: Support for OpenId Connect; Removed: Support for LDAP.
1 <?php 2 3 /** 4 * Pure-PHP arbitrary precision integer arithmetic library. 5 * 6 * Supports base-2, base-10, base-16, and base-256 numbers. Uses the GMP or BCMath extensions, if available, 7 * and an internal implementation, otherwise. 8 * 9 * PHP version 5 10 * 11 * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the 12 * {@link self::MODE_INTERNAL self::MODE_INTERNAL} mode) 13 * 14 * BigInteger uses base-2**26 to perform operations such as multiplication and division and 15 * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction. Because the largest possible 16 * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating 17 * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are 18 * used. As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %, 19 * which only supports integers. Although this fact will slow this library down, the fact that such a high 20 * base is being used should more than compensate. 21 * 22 * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie. 23 * (new \phpseclib\Math\BigInteger(pow(2, 26)))->value = array(0, 1) 24 * 25 * Useful resources are as follows: 26 * 27 * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)} 28 * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)} 29 * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip 30 * 31 * Here's an example of how to use this library: 32 * <code> 33 * <?php 34 * $a = new \phpseclib\Math\BigInteger(2); 35 * $b = new \phpseclib\Math\BigInteger(3); 36 * 37 * $c = $a->add($b); 38 * 39 * echo $c->toString(); // outputs 5 40 * ?> 41 * </code> 42 * 43 * @category Math 44 * @package BigInteger 45 * @author Jim Wigginton <terrafrost@php.net> 46 * @copyright 2006 Jim Wigginton 47 * @license http://www.opensource.org/licenses/mit-license.html MIT License 48 */ 49 50 namespace phpseclib\Math; 51 52 use phpseclib\Crypt\Random; 53 54 /** 55 * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 56 * numbers. 57 * 58 * @package BigInteger 59 * @author Jim Wigginton <terrafrost@php.net> 60 * @access public 61 */ 62 class BigInteger 63 { 64 /**#@+ 65 * Reduction constants 66 * 67 * @access private 68 * @see BigInteger::_reduce() 69 */ 70 /** 71 * @see BigInteger::_montgomery() 72 * @see BigInteger::_prepMontgomery() 73 */ 74 const MONTGOMERY = 0; 75 /** 76 * @see BigInteger::_barrett() 77 */ 78 const BARRETT = 1; 79 /** 80 * @see BigInteger::_mod2() 81 */ 82 const POWEROF2 = 2; 83 /** 84 * @see BigInteger::_remainder() 85 */ 86 const CLASSIC = 3; 87 /** 88 * @see BigInteger::__clone() 89 */ 90 const NONE = 4; 91 /**#@-*/ 92 93 /**#@+ 94 * Array constants 95 * 96 * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and 97 * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them. 98 * 99 * @access private 100 */ 101 /** 102 * $result[self::VALUE] contains the value. 103 */ 104 const VALUE = 0; 105 /** 106 * $result[self::SIGN] contains the sign. 107 */ 108 const SIGN = 1; 109 /**#@-*/ 110 111 /**#@+ 112 * @access private 113 * @see BigInteger::_montgomery() 114 * @see BigInteger::_barrett() 115 */ 116 /** 117 * Cache constants 118 * 119 * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. 120 */ 121 const VARIABLE = 0; 122 /** 123 * $cache[self::DATA] contains the cached data. 124 */ 125 const DATA = 1; 126 /**#@-*/ 127 128 /**#@+ 129 * Mode constants. 130 * 131 * @access private 132 * @see BigInteger::__construct() 133 */ 134 /** 135 * To use the pure-PHP implementation 136 */ 137 const MODE_INTERNAL = 1; 138 /** 139 * To use the BCMath library 140 * 141 * (if enabled; otherwise, the internal implementation will be used) 142 */ 143 const MODE_BCMATH = 2; 144 /** 145 * To use the GMP library 146 * 147 * (if present; otherwise, either the BCMath or the internal implementation will be used) 148 */ 149 const MODE_GMP = 3; 150 /**#@-*/ 151 152 /** 153 * Karatsuba Cutoff 154 * 155 * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication? 156 * 157 * @access private 158 */ 159 const KARATSUBA_CUTOFF = 25; 160 161 /**#@+ 162 * Static properties used by the pure-PHP implementation. 163 * 164 * @see __construct() 165 */ 166 protected static $base; 167 protected static $baseFull; 168 protected static $maxDigit; 169 protected static $msb; 170 171 /** 172 * $max10 in greatest $max10Len satisfying 173 * $max10 = 10**$max10Len <= 2**$base. 174 */ 175 protected static $max10; 176 177 /** 178 * $max10Len in greatest $max10Len satisfying 179 * $max10 = 10**$max10Len <= 2**$base. 180 */ 181 protected static $max10Len; 182 protected static $maxDigit2; 183 /**#@-*/ 184 185 /** 186 * Holds the BigInteger's value. 187 * 188 * @var array 189 * @access private 190 */ 191 var $value; 192 193 /** 194 * Holds the BigInteger's magnitude. 195 * 196 * @var bool 197 * @access private 198 */ 199 var $is_negative = false; 200 201 /** 202 * Precision 203 * 204 * @see self::setPrecision() 205 * @access private 206 */ 207 var $precision = -1; 208 209 /** 210 * Precision Bitmask 211 * 212 * @see self::setPrecision() 213 * @access private 214 */ 215 var $bitmask = false; 216 217 /** 218 * Mode independent value used for serialization. 219 * 220 * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for 221 * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value, 222 * however, $this->hex is only calculated when $this->__sleep() is called. 223 * 224 * @see self::__sleep() 225 * @see self::__wakeup() 226 * @var string 227 * @access private 228 */ 229 var $hex; 230 231 /** 232 * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers. 233 * 234 * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using 235 * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. 236 * 237 * Here's an example: 238 * <code> 239 * <?php 240 * $a = new \phpseclib\Math\BigInteger('0x32', 16); // 50 in base-16 241 * 242 * echo $a->toString(); // outputs 50 243 * ?> 244 * </code> 245 * 246 * @param $x base-10 number or base-$base number if $base set. 247 * @param int $base 248 * @return \phpseclib\Math\BigInteger 249 * @access public 250 */ 251 function __construct($x = 0, $base = 10) 252 { 253 if (!defined('MATH_BIGINTEGER_MODE')) { 254 switch (true) { 255 case extension_loaded('gmp'): 256 define('MATH_BIGINTEGER_MODE', self::MODE_GMP); 257 break; 258 case extension_loaded('bcmath'): 259 define('MATH_BIGINTEGER_MODE', self::MODE_BCMATH); 260 break; 261 default: 262 define('MATH_BIGINTEGER_MODE', self::MODE_INTERNAL); 263 } 264 } 265 266 if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { 267 // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work 268 $versions = array(); 269 270 // avoid generating errors (even with suppression) when phpinfo() is disabled (common in production systems) 271 if (strpos(ini_get('disable_functions'), 'phpinfo') === false) { 272 ob_start(); 273 @phpinfo(); 274 $content = ob_get_contents(); 275 ob_end_clean(); 276 277 preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches); 278 279 if (!empty($matches[1])) { 280 for ($i = 0; $i < count($matches[1]); $i++) { 281 $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i]))); 282 283 // Remove letter part in OpenSSL version 284 if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) { 285 $versions[$matches[1][$i]] = $fullVersion; 286 } else { 287 $versions[$matches[1][$i]] = $m[0]; 288 } 289 } 290 } 291 } 292 293 // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+ 294 switch (true) { 295 case !isset($versions['Header']): 296 case !isset($versions['Library']): 297 case $versions['Header'] == $versions['Library']: 298 case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0: 299 define('MATH_BIGINTEGER_OPENSSL_ENABLED', true); 300 break; 301 default: 302 define('MATH_BIGINTEGER_OPENSSL_DISABLE', true); 303 } 304 } 305 306 if (!defined('PHP_INT_SIZE')) { 307 define('PHP_INT_SIZE', 4); 308 } 309 310 if (empty(self::$base) && MATH_BIGINTEGER_MODE == self::MODE_INTERNAL) { 311 switch (PHP_INT_SIZE) { 312 case 8: // use 64-bit integers if int size is 8 bytes 313 self::$base = 31; 314 self::$baseFull = 0x80000000; 315 self::$maxDigit = 0x7FFFFFFF; 316 self::$msb = 0x40000000; 317 self::$max10 = 1000000000; 318 self::$max10Len = 9; 319 self::$maxDigit2 = pow(2, 62); 320 break; 321 //case 4: // use 64-bit floats if int size is 4 bytes 322 default: 323 self::$base = 26; 324 self::$baseFull = 0x4000000; 325 self::$maxDigit = 0x3FFFFFF; 326 self::$msb = 0x2000000; 327 self::$max10 = 10000000; 328 self::$max10Len = 7; 329 self::$maxDigit2 = pow(2, 52); // pow() prevents truncation 330 } 331 } 332 333 switch (MATH_BIGINTEGER_MODE) { 334 case self::MODE_GMP: 335 switch (true) { 336 case is_resource($x) && get_resource_type($x) == 'GMP integer': 337 // PHP 5.6 switched GMP from using resources to objects 338 case $x instanceof \GMP: 339 $this->value = $x; 340 return; 341 } 342 $this->value = gmp_init(0); 343 break; 344 case self::MODE_BCMATH: 345 $this->value = '0'; 346 break; 347 default: 348 $this->value = array(); 349 } 350 351 // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48 352 // '0' is the only value like this per http://php.net/empty 353 if (empty($x) && (abs($base) != 256 || $x !== '0')) { 354 return; 355 } 356 357 switch ($base) { 358 case -256: 359 if (ord($x[0]) & 0x80) { 360 $x = ~$x; 361 $this->is_negative = true; 362 } 363 case 256: 364 switch (MATH_BIGINTEGER_MODE) { 365 case self::MODE_GMP: 366 $this->value = function_exists('gmp_import') ? 367 gmp_import($x) : 368 gmp_init('0x' . bin2hex($x)); 369 if ($this->is_negative) { 370 $this->value = gmp_neg($this->value); 371 } 372 break; 373 case self::MODE_BCMATH: 374 // round $len to the nearest 4 (thanks, DavidMJ!) 375 $len = (strlen($x) + 3) & 0xFFFFFFFC; 376 377 $x = str_pad($x, $len, chr(0), STR_PAD_LEFT); 378 379 for ($i = 0; $i < $len; $i+= 4) { 380 $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32 381 $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0); 382 } 383 384 if ($this->is_negative) { 385 $this->value = '-' . $this->value; 386 } 387 388 break; 389 // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb) 390 default: 391 while (strlen($x)) { 392 $this->value[] = $this->_bytes2int($this->_base256_rshift($x, self::$base)); 393 } 394 } 395 396 if ($this->is_negative) { 397 if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { 398 $this->is_negative = false; 399 } 400 $temp = $this->add(new static('-1')); 401 $this->value = $temp->value; 402 } 403 break; 404 case 16: 405 case -16: 406 if ($base > 0 && $x[0] == '-') { 407 $this->is_negative = true; 408 $x = substr($x, 1); 409 } 410 411 $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x); 412 413 $is_negative = false; 414 if ($base < 0 && hexdec($x[0]) >= 8) { 415 $this->is_negative = $is_negative = true; 416 $x = bin2hex(~pack('H*', $x)); 417 } 418 419 switch (MATH_BIGINTEGER_MODE) { 420 case self::MODE_GMP: 421 $temp = $this->is_negative ? '-0x' . $x : '0x' . $x; 422 $this->value = gmp_init($temp); 423 $this->is_negative = false; 424 break; 425 case self::MODE_BCMATH: 426 $x = (strlen($x) & 1) ? '0' . $x : $x; 427 $temp = new static(pack('H*', $x), 256); 428 $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; 429 $this->is_negative = false; 430 break; 431 default: 432 $x = (strlen($x) & 1) ? '0' . $x : $x; 433 $temp = new static(pack('H*', $x), 256); 434 $this->value = $temp->value; 435 } 436 437 if ($is_negative) { 438 $temp = $this->add(new static('-1')); 439 $this->value = $temp->value; 440 } 441 break; 442 case 10: 443 case -10: 444 // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that 445 // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals) 446 // [^-0-9].*: find any non-numeric characters and then any characters that follow that 447 $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x); 448 if (!strlen($x) || $x == '-') { 449 $x = '0'; 450 } 451 452 switch (MATH_BIGINTEGER_MODE) { 453 case self::MODE_GMP: 454 $this->value = gmp_init($x); 455 break; 456 case self::MODE_BCMATH: 457 // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different 458 // results then doing it on '-1' does (modInverse does $x[0]) 459 $this->value = $x === '-' ? '0' : (string) $x; 460 break; 461 default: 462 $temp = new static(); 463 464 $multiplier = new static(); 465 $multiplier->value = array(self::$max10); 466 467 if ($x[0] == '-') { 468 $this->is_negative = true; 469 $x = substr($x, 1); 470 } 471 472 $x = str_pad($x, strlen($x) + ((self::$max10Len - 1) * strlen($x)) % self::$max10Len, 0, STR_PAD_LEFT); 473 while (strlen($x)) { 474 $temp = $temp->multiply($multiplier); 475 $temp = $temp->add(new static($this->_int2bytes(substr($x, 0, self::$max10Len)), 256)); 476 $x = substr($x, self::$max10Len); 477 } 478 479 $this->value = $temp->value; 480 } 481 break; 482 case 2: // base-2 support originally implemented by Lluis Pamies - thanks! 483 case -2: 484 if ($base > 0 && $x[0] == '-') { 485 $this->is_negative = true; 486 $x = substr($x, 1); 487 } 488 489 $x = preg_replace('#^([01]*).*#', '$1', $x); 490 $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT); 491 492 $str = '0x'; 493 while (strlen($x)) { 494 $part = substr($x, 0, 4); 495 $str.= dechex(bindec($part)); 496 $x = substr($x, 4); 497 } 498 499 if ($this->is_negative) { 500 $str = '-' . $str; 501 } 502 503 $temp = new static($str, 8 * $base); // ie. either -16 or +16 504 $this->value = $temp->value; 505 $this->is_negative = $temp->is_negative; 506 507 break; 508 default: 509 // base not supported, so we'll let $this == 0 510 } 511 } 512 513 /** 514 * Converts a BigInteger to a byte string (eg. base-256). 515 * 516 * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're 517 * saved as two's compliment. 518 * 519 * Here's an example: 520 * <code> 521 * <?php 522 * $a = new \phpseclib\Math\BigInteger('65'); 523 * 524 * echo $a->toBytes(); // outputs chr(65) 525 * ?> 526 * </code> 527 * 528 * @param bool $twos_compliment 529 * @return string 530 * @access public 531 * @internal Converts a base-2**26 number to base-2**8 532 */ 533 function toBytes($twos_compliment = false) 534 { 535 if ($twos_compliment) { 536 $comparison = $this->compare(new static()); 537 if ($comparison == 0) { 538 return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; 539 } 540 541 $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy(); 542 $bytes = $temp->toBytes(); 543 544 if (!strlen($bytes)) { // eg. if the number we're trying to convert is -1 545 $bytes = chr(0); 546 } 547 548 if ($this->precision <= 0 && (ord($bytes[0]) & 0x80)) { 549 $bytes = chr(0) . $bytes; 550 } 551 552 return $comparison < 0 ? ~$bytes : $bytes; 553 } 554 555 switch (MATH_BIGINTEGER_MODE) { 556 case self::MODE_GMP: 557 if (gmp_cmp($this->value, gmp_init(0)) == 0) { 558 return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; 559 } 560 561 if (function_exists('gmp_export')) { 562 $temp = gmp_export($this->value); 563 } else { 564 $temp = gmp_strval(gmp_abs($this->value), 16); 565 $temp = (strlen($temp) & 1) ? '0' . $temp : $temp; 566 $temp = pack('H*', $temp); 567 } 568 569 return $this->precision > 0 ? 570 substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : 571 ltrim($temp, chr(0)); 572 case self::MODE_BCMATH: 573 if ($this->value === '0') { 574 return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; 575 } 576 577 $value = ''; 578 $current = $this->value; 579 580 if ($current[0] == '-') { 581 $current = substr($current, 1); 582 } 583 584 while (bccomp($current, '0', 0) > 0) { 585 $temp = bcmod($current, '16777216'); 586 $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value; 587 $current = bcdiv($current, '16777216', 0); 588 } 589 590 return $this->precision > 0 ? 591 substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : 592 ltrim($value, chr(0)); 593 } 594 595 if (!count($this->value)) { 596 return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; 597 } 598 $result = $this->_int2bytes($this->value[count($this->value) - 1]); 599 600 $temp = $this->copy(); 601 602 for ($i = count($temp->value) - 2; $i >= 0; --$i) { 603 $temp->_base256_lshift($result, self::$base); 604 $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); 605 } 606 607 return $this->precision > 0 ? 608 str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) : 609 $result; 610 } 611 612 /** 613 * Converts a BigInteger to a hex string (eg. base-16)). 614 * 615 * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're 616 * saved as two's compliment. 617 * 618 * Here's an example: 619 * <code> 620 * <?php 621 * $a = new \phpseclib\Math\BigInteger('65'); 622 * 623 * echo $a->toHex(); // outputs '41' 624 * ?> 625 * </code> 626 * 627 * @param bool $twos_compliment 628 * @return string 629 * @access public 630 * @internal Converts a base-2**26 number to base-2**8 631 */ 632 function toHex($twos_compliment = false) 633 { 634 return bin2hex($this->toBytes($twos_compliment)); 635 } 636 637 /** 638 * Converts a BigInteger to a bit string (eg. base-2). 639 * 640 * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're 641 * saved as two's compliment. 642 * 643 * Here's an example: 644 * <code> 645 * <?php 646 * $a = new \phpseclib\Math\BigInteger('65'); 647 * 648 * echo $a->toBits(); // outputs '1000001' 649 * ?> 650 * </code> 651 * 652 * @param bool $twos_compliment 653 * @return string 654 * @access public 655 * @internal Converts a base-2**26 number to base-2**2 656 */ 657 function toBits($twos_compliment = false) 658 { 659 $hex = $this->toHex($twos_compliment); 660 $bits = ''; 661 for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) { 662 $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits; 663 } 664 if ($start) { // hexdec('') == 0 665 $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits; 666 } 667 $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); 668 669 if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) { 670 return '0' . $result; 671 } 672 673 return $result; 674 } 675 676 /** 677 * Converts a BigInteger to a base-10 number. 678 * 679 * Here's an example: 680 * <code> 681 * <?php 682 * $a = new \phpseclib\Math\BigInteger('50'); 683 * 684 * echo $a->toString(); // outputs 50 685 * ?> 686 * </code> 687 * 688 * @return string 689 * @access public 690 * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10) 691 */ 692 function toString() 693 { 694 switch (MATH_BIGINTEGER_MODE) { 695 case self::MODE_GMP: 696 return gmp_strval($this->value); 697 case self::MODE_BCMATH: 698 if ($this->value === '0') { 699 return '0'; 700 } 701 702 return ltrim($this->value, '0'); 703 } 704 705 if (!count($this->value)) { 706 return '0'; 707 } 708 709 $temp = $this->copy(); 710 $temp->bitmask = false; 711 $temp->is_negative = false; 712 713 $divisor = new static(); 714 $divisor->value = array(self::$max10); 715 $result = ''; 716 while (count($temp->value)) { 717 list($temp, $mod) = $temp->divide($divisor); 718 $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', self::$max10Len, '0', STR_PAD_LEFT) . $result; 719 } 720 $result = ltrim($result, '0'); 721 if (empty($result)) { 722 $result = '0'; 723 } 724 725 if ($this->is_negative) { 726 $result = '-' . $result; 727 } 728 729 return $result; 730 } 731 732 /** 733 * Copy an object 734 * 735 * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee 736 * that all objects are passed by value, when appropriate. More information can be found here: 737 * 738 * {@link http://php.net/language.oop5.basic#51624} 739 * 740 * @access public 741 * @see self::__clone() 742 * @return \phpseclib\Math\BigInteger 743 */ 744 function copy() 745 { 746 $temp = new static(); 747 $temp->value = $this->value; 748 $temp->is_negative = $this->is_negative; 749 $temp->precision = $this->precision; 750 $temp->bitmask = $this->bitmask; 751 return $temp; 752 } 753 754 /** 755 * __toString() magic method 756 * 757 * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call 758 * toString(). 759 * 760 * @access public 761 * @internal Implemented per a suggestion by Techie-Michael - thanks! 762 */ 763 function __toString() 764 { 765 return $this->toString(); 766 } 767 768 /** 769 * __clone() magic method 770 * 771 * Although you can call BigInteger::__toString() directly in PHP5, you cannot call BigInteger::__clone() directly 772 * in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5 773 * only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and 774 * PHP5, call BigInteger::copy(), instead. 775 * 776 * @access public 777 * @see self::copy() 778 * @return \phpseclib\Math\BigInteger 779 */ 780 function __clone() 781 { 782 return $this->copy(); 783 } 784 785 /** 786 * __sleep() magic method 787 * 788 * Will be called, automatically, when serialize() is called on a BigInteger object. 789 * 790 * @see self::__wakeup() 791 * @access public 792 */ 793 function __sleep() 794 { 795 $this->hex = $this->toHex(true); 796 $vars = array('hex'); 797 if ($this->precision > 0) { 798 $vars[] = 'precision'; 799 } 800 return $vars; 801 } 802 803 /** 804 * __wakeup() magic method 805 * 806 * Will be called, automatically, when unserialize() is called on a BigInteger object. 807 * 808 * @see self::__sleep() 809 * @access public 810 */ 811 function __wakeup() 812 { 813 $temp = new static($this->hex, -16); 814 $this->value = $temp->value; 815 $this->is_negative = $temp->is_negative; 816 if ($this->precision > 0) { 817 // recalculate $this->bitmask 818 $this->setPrecision($this->precision); 819 } 820 } 821 822 /** 823 * __debugInfo() magic method 824 * 825 * Will be called, automatically, when print_r() or var_dump() are called 826 * 827 * @access public 828 */ 829 function __debugInfo() 830 { 831 $opts = array(); 832 switch (MATH_BIGINTEGER_MODE) { 833 case self::MODE_GMP: 834 $engine = 'gmp'; 835 break; 836 case self::MODE_BCMATH: 837 $engine = 'bcmath'; 838 break; 839 case self::MODE_INTERNAL: 840 $engine = 'internal'; 841 $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit'; 842 } 843 if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { 844 $opts[] = 'OpenSSL'; 845 } 846 if (!empty($opts)) { 847 $engine.= ' (' . implode('.', $opts) . ')'; 848 } 849 return array( 850 'value' => '0x' . $this->toHex(true), 851 'engine' => $engine 852 ); 853 } 854 855 /** 856 * Adds two BigIntegers. 857 * 858 * Here's an example: 859 * <code> 860 * <?php 861 * $a = new \phpseclib\Math\BigInteger('10'); 862 * $b = new \phpseclib\Math\BigInteger('20'); 863 * 864 * $c = $a->add($b); 865 * 866 * echo $c->toString(); // outputs 30 867 * ?> 868 * </code> 869 * 870 * @param \phpseclib\Math\BigInteger $y 871 * @return \phpseclib\Math\BigInteger 872 * @access public 873 * @internal Performs base-2**52 addition 874 */ 875 function add($y) 876 { 877 switch (MATH_BIGINTEGER_MODE) { 878 case self::MODE_GMP: 879 $temp = new static(); 880 $temp->value = gmp_add($this->value, $y->value); 881 882 return $this->_normalize($temp); 883 case self::MODE_BCMATH: 884 $temp = new static(); 885 $temp->value = bcadd($this->value, $y->value, 0); 886 887 return $this->_normalize($temp); 888 } 889 890 $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative); 891 892 $result = new static(); 893 $result->value = $temp[self::VALUE]; 894 $result->is_negative = $temp[self::SIGN]; 895 896 return $this->_normalize($result); 897 } 898 899 /** 900 * Performs addition. 901 * 902 * @param array $x_value 903 * @param bool $x_negative 904 * @param array $y_value 905 * @param bool $y_negative 906 * @return array 907 * @access private 908 */ 909 function _add($x_value, $x_negative, $y_value, $y_negative) 910 { 911 $x_size = count($x_value); 912 $y_size = count($y_value); 913 914 if ($x_size == 0) { 915 return array( 916 self::VALUE => $y_value, 917 self::SIGN => $y_negative 918 ); 919 } elseif ($y_size == 0) { 920 return array( 921 self::VALUE => $x_value, 922 self::SIGN => $x_negative 923 ); 924 } 925 926 // subtract, if appropriate 927 if ($x_negative != $y_negative) { 928 if ($x_value == $y_value) { 929 return array( 930 self::VALUE => array(), 931 self::SIGN => false 932 ); 933 } 934 935 $temp = $this->_subtract($x_value, false, $y_value, false); 936 $temp[self::SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ? 937 $x_negative : $y_negative; 938 939 return $temp; 940 } 941 942 if ($x_size < $y_size) { 943 $size = $x_size; 944 $value = $y_value; 945 } else { 946 $size = $y_size; 947 $value = $x_value; 948 } 949 950 $value[count($value)] = 0; // just in case the carry adds an extra digit 951 952 $carry = 0; 953 for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) { 954 $sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry; 955 $carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 956 $sum = $carry ? $sum - self::$maxDigit2 : $sum; 957 958 $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31); 959 960 $value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000) 961 $value[$j] = $temp; 962 } 963 964 if ($j == $size) { // ie. if $y_size is odd 965 $sum = $x_value[$i] + $y_value[$i] + $carry; 966 $carry = $sum >= self::$baseFull; 967 $value[$i] = $carry ? $sum - self::$baseFull : $sum; 968 ++$i; // ie. let $i = $j since we've just done $value[$i] 969 } 970 971 if ($carry) { 972 for (; $value[$i] == self::$maxDigit; ++$i) { 973 $value[$i] = 0; 974 } 975 ++$value[$i]; 976 } 977 978 return array( 979 self::VALUE => $this->_trim($value), 980 self::SIGN => $x_negative 981 ); 982 } 983 984 /** 985 * Subtracts two BigIntegers. 986 * 987 * Here's an example: 988 * <code> 989 * <?php 990 * $a = new \phpseclib\Math\BigInteger('10'); 991 * $b = new \phpseclib\Math\BigInteger('20'); 992 * 993 * $c = $a->subtract($b); 994 * 995 * echo $c->toString(); // outputs -10 996 * ?> 997 * </code> 998 * 999 * @param \phpseclib\Math\BigInteger $y 1000 * @return \phpseclib\Math\BigInteger 1001 * @access public 1002 * @internal Performs base-2**52 subtraction 1003 */ 1004 function subtract($y) 1005 { 1006 switch (MATH_BIGINTEGER_MODE) { 1007 case self::MODE_GMP: 1008 $temp = new static(); 1009 $temp->value = gmp_sub($this->value, $y->value); 1010 1011 return $this->_normalize($temp); 1012 case self::MODE_BCMATH: 1013 $temp = new static(); 1014 $temp->value = bcsub($this->value, $y->value, 0); 1015 1016 return $this->_normalize($temp); 1017 } 1018 1019 $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative); 1020 1021 $result = new static(); 1022 $result->value = $temp[self::VALUE]; 1023 $result->is_negative = $temp[self::SIGN]; 1024 1025 return $this->_normalize($result); 1026 } 1027 1028 /** 1029 * Performs subtraction. 1030 * 1031 * @param array $x_value 1032 * @param bool $x_negative 1033 * @param array $y_value 1034 * @param bool $y_negative 1035 * @return array 1036 * @access private 1037 */ 1038 function _subtract($x_value, $x_negative, $y_value, $y_negative) 1039 { 1040 $x_size = count($x_value); 1041 $y_size = count($y_value); 1042 1043 if ($x_size == 0) { 1044 return array( 1045 self::VALUE => $y_value, 1046 self::SIGN => !$y_negative 1047 ); 1048 } elseif ($y_size == 0) { 1049 return array( 1050 self::VALUE => $x_value, 1051 self::SIGN => $x_negative 1052 ); 1053 } 1054 1055 // add, if appropriate (ie. -$x - +$y or +$x - -$y) 1056 if ($x_negative != $y_negative) { 1057 $temp = $this->_add($x_value, false, $y_value, false); 1058 $temp[self::SIGN] = $x_negative; 1059 1060 return $temp; 1061 } 1062 1063 $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative); 1064 1065 if (!$diff) { 1066 return array( 1067 self::VALUE => array(), 1068 self::SIGN => false 1069 ); 1070 } 1071 1072 // switch $x and $y around, if appropriate. 1073 if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) { 1074 $temp = $x_value; 1075 $x_value = $y_value; 1076 $y_value = $temp; 1077 1078 $x_negative = !$x_negative; 1079 1080 $x_size = count($x_value); 1081 $y_size = count($y_value); 1082 } 1083 1084 // at this point, $x_value should be at least as big as - if not bigger than - $y_value 1085 1086 $carry = 0; 1087 for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) { 1088 $sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry; 1089 $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 1090 $sum = $carry ? $sum + self::$maxDigit2 : $sum; 1091 1092 $temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31); 1093 1094 $x_value[$i] = (int) ($sum - self::$baseFull * $temp); 1095 $x_value[$j] = $temp; 1096 } 1097 1098 if ($j == $y_size) { // ie. if $y_size is odd 1099 $sum = $x_value[$i] - $y_value[$i] - $carry; 1100 $carry = $sum < 0; 1101 $x_value[$i] = $carry ? $sum + self::$baseFull : $sum; 1102 ++$i; 1103 } 1104 1105 if ($carry) { 1106 for (; !$x_value[$i]; ++$i) { 1107 $x_value[$i] = self::$maxDigit; 1108 } 1109 --$x_value[$i]; 1110 } 1111 1112 return array( 1113 self::VALUE => $this->_trim($x_value), 1114 self::SIGN => $x_negative 1115 ); 1116 } 1117 1118 /** 1119 * Multiplies two BigIntegers 1120 * 1121 * Here's an example: 1122 * <code> 1123 * <?php 1124 * $a = new \phpseclib\Math\BigInteger('10'); 1125 * $b = new \phpseclib\Math\BigInteger('20'); 1126 * 1127 * $c = $a->multiply($b); 1128 * 1129 * echo $c->toString(); // outputs 200 1130 * ?> 1131 * </code> 1132 * 1133 * @param \phpseclib\Math\BigInteger $x 1134 * @return \phpseclib\Math\BigInteger 1135 * @access public 1136 */ 1137 function multiply($x) 1138 { 1139 switch (MATH_BIGINTEGER_MODE) { 1140 case self::MODE_GMP: 1141 $temp = new static(); 1142 $temp->value = gmp_mul($this->value, $x->value); 1143 1144 return $this->_normalize($temp); 1145 case self::MODE_BCMATH: 1146 $temp = new static(); 1147 $temp->value = bcmul($this->value, $x->value, 0); 1148 1149 return $this->_normalize($temp); 1150 } 1151 1152 $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative); 1153 1154 $product = new static(); 1155 $product->value = $temp[self::VALUE]; 1156 $product->is_negative = $temp[self::SIGN]; 1157 1158 return $this->_normalize($product); 1159 } 1160 1161 /** 1162 * Performs multiplication. 1163 * 1164 * @param array $x_value 1165 * @param bool $x_negative 1166 * @param array $y_value 1167 * @param bool $y_negative 1168 * @return array 1169 * @access private 1170 */ 1171 function _multiply($x_value, $x_negative, $y_value, $y_negative) 1172 { 1173 //if ( $x_value == $y_value ) { 1174 // return array( 1175 // self::VALUE => $this->_square($x_value), 1176 // self::SIGN => $x_sign != $y_value 1177 // ); 1178 //} 1179 1180 $x_length = count($x_value); 1181 $y_length = count($y_value); 1182 1183 if (!$x_length || !$y_length) { // a 0 is being multiplied 1184 return array( 1185 self::VALUE => array(), 1186 self::SIGN => false 1187 ); 1188 } 1189 1190 return array( 1191 self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ? 1192 $this->_trim($this->_regularMultiply($x_value, $y_value)) : 1193 $this->_trim($this->_karatsuba($x_value, $y_value)), 1194 self::SIGN => $x_negative != $y_negative 1195 ); 1196 } 1197 1198 /** 1199 * Performs long multiplication on two BigIntegers 1200 * 1201 * Modeled after 'multiply' in MutableBigInteger.java. 1202 * 1203 * @param array $x_value 1204 * @param array $y_value 1205 * @return array 1206 * @access private 1207 */ 1208 function _regularMultiply($x_value, $y_value) 1209 { 1210 $x_length = count($x_value); 1211 $y_length = count($y_value); 1212 1213 if (!$x_length || !$y_length) { // a 0 is being multiplied 1214 return array(); 1215 } 1216 1217 if ($x_length < $y_length) { 1218 $temp = $x_value; 1219 $x_value = $y_value; 1220 $y_value = $temp; 1221 1222 $x_length = count($x_value); 1223 $y_length = count($y_value); 1224 } 1225 1226 $product_value = $this->_array_repeat(0, $x_length + $y_length); 1227 1228 // the following for loop could be removed if the for loop following it 1229 // (the one with nested for loops) initially set $i to 0, but 1230 // doing so would also make the result in one set of unnecessary adds, 1231 // since on the outermost loops first pass, $product->value[$k] is going 1232 // to always be 0 1233 1234 $carry = 0; 1235 1236 for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0 1237 $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 1238 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 1239 $product_value[$j] = (int) ($temp - self::$baseFull * $carry); 1240 } 1241 1242 $product_value[$j] = $carry; 1243 1244 // the above for loop is what the previous comment was talking about. the 1245 // following for loop is the "one with nested for loops" 1246 for ($i = 1; $i < $y_length; ++$i) { 1247 $carry = 0; 1248 1249 for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) { 1250 $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; 1251 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 1252 $product_value[$k] = (int) ($temp - self::$baseFull * $carry); 1253 } 1254 1255 $product_value[$k] = $carry; 1256 } 1257 1258 return $product_value; 1259 } 1260 1261 /** 1262 * Performs Karatsuba multiplication on two BigIntegers 1263 * 1264 * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and 1265 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}. 1266 * 1267 * @param array $x_value 1268 * @param array $y_value 1269 * @return array 1270 * @access private 1271 */ 1272 function _karatsuba($x_value, $y_value) 1273 { 1274 $m = min(count($x_value) >> 1, count($y_value) >> 1); 1275 1276 if ($m < self::KARATSUBA_CUTOFF) { 1277 return $this->_regularMultiply($x_value, $y_value); 1278 } 1279 1280 $x1 = array_slice($x_value, $m); 1281 $x0 = array_slice($x_value, 0, $m); 1282 $y1 = array_slice($y_value, $m); 1283 $y0 = array_slice($y_value, 0, $m); 1284 1285 $z2 = $this->_karatsuba($x1, $y1); 1286 $z0 = $this->_karatsuba($x0, $y0); 1287 1288 $z1 = $this->_add($x1, false, $x0, false); 1289 $temp = $this->_add($y1, false, $y0, false); 1290 $z1 = $this->_karatsuba($z1[self::VALUE], $temp[self::VALUE]); 1291 $temp = $this->_add($z2, false, $z0, false); 1292 $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false); 1293 1294 $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); 1295 $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); 1296 1297 $xy = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); 1298 $xy = $this->_add($xy[self::VALUE], $xy[self::SIGN], $z0, false); 1299 1300 return $xy[self::VALUE]; 1301 } 1302 1303 /** 1304 * Performs squaring 1305 * 1306 * @param array $x 1307 * @return array 1308 * @access private 1309 */ 1310 function _square($x = false) 1311 { 1312 return count($x) < 2 * self::KARATSUBA_CUTOFF ? 1313 $this->_trim($this->_baseSquare($x)) : 1314 $this->_trim($this->_karatsubaSquare($x)); 1315 } 1316 1317 /** 1318 * Performs traditional squaring on two BigIntegers 1319 * 1320 * Squaring can be done faster than multiplying a number by itself can be. See 1321 * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} / 1322 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information. 1323 * 1324 * @param array $value 1325 * @return array 1326 * @access private 1327 */ 1328 function _baseSquare($value) 1329 { 1330 if (empty($value)) { 1331 return array(); 1332 } 1333 $square_value = $this->_array_repeat(0, 2 * count($value)); 1334 1335 for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) { 1336 $i2 = $i << 1; 1337 1338 $temp = $square_value[$i2] + $value[$i] * $value[$i]; 1339 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 1340 $square_value[$i2] = (int) ($temp - self::$baseFull * $carry); 1341 1342 // note how we start from $i+1 instead of 0 as we do in multiplication. 1343 for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) { 1344 $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry; 1345 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 1346 $square_value[$k] = (int) ($temp - self::$baseFull * $carry); 1347 } 1348 1349 // the following line can yield values larger 2**15. at this point, PHP should switch 1350 // over to floats. 1351 $square_value[$i + $max_index + 1] = $carry; 1352 } 1353 1354 return $square_value; 1355 } 1356 1357 /** 1358 * Performs Karatsuba "squaring" on two BigIntegers 1359 * 1360 * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and 1361 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}. 1362 * 1363 * @param array $value 1364 * @return array 1365 * @access private 1366 */ 1367 function _karatsubaSquare($value) 1368 { 1369 $m = count($value) >> 1; 1370 1371 if ($m < self::KARATSUBA_CUTOFF) { 1372 return $this->_baseSquare($value); 1373 } 1374 1375 $x1 = array_slice($value, $m); 1376 $x0 = array_slice($value, 0, $m); 1377 1378 $z2 = $this->_karatsubaSquare($x1); 1379 $z0 = $this->_karatsubaSquare($x0); 1380 1381 $z1 = $this->_add($x1, false, $x0, false); 1382 $z1 = $this->_karatsubaSquare($z1[self::VALUE]); 1383 $temp = $this->_add($z2, false, $z0, false); 1384 $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false); 1385 1386 $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); 1387 $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); 1388 1389 $xx = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); 1390 $xx = $this->_add($xx[self::VALUE], $xx[self::SIGN], $z0, false); 1391 1392 return $xx[self::VALUE]; 1393 } 1394 1395 /** 1396 * Divides two BigIntegers. 1397 * 1398 * Returns an array whose first element contains the quotient and whose second element contains the 1399 * "common residue". If the remainder would be positive, the "common residue" and the remainder are the 1400 * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder 1401 * and the divisor (basically, the "common residue" is the first positive modulo). 1402 * 1403 * Here's an example: 1404 * <code> 1405 * <?php 1406 * $a = new \phpseclib\Math\BigInteger('10'); 1407 * $b = new \phpseclib\Math\BigInteger('20'); 1408 * 1409 * list($quotient, $remainder) = $a->divide($b); 1410 * 1411 * echo $quotient->toString(); // outputs 0 1412 * echo "\r\n"; 1413 * echo $remainder->toString(); // outputs 10 1414 * ?> 1415 * </code> 1416 * 1417 * @param \phpseclib\Math\BigInteger $y 1418 * @return array 1419 * @access public 1420 * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}. 1421 */ 1422 function divide($y) 1423 { 1424 switch (MATH_BIGINTEGER_MODE) { 1425 case self::MODE_GMP: 1426 $quotient = new static(); 1427 $remainder = new static(); 1428 1429 list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value); 1430 1431 if (gmp_sign($remainder->value) < 0) { 1432 $remainder->value = gmp_add($remainder->value, gmp_abs($y->value)); 1433 } 1434 1435 return array($this->_normalize($quotient), $this->_normalize($remainder)); 1436 case self::MODE_BCMATH: 1437 $quotient = new static(); 1438 $remainder = new static(); 1439 1440 $quotient->value = bcdiv($this->value, $y->value, 0); 1441 $remainder->value = bcmod($this->value, $y->value); 1442 1443 if ($remainder->value[0] == '-') { 1444 $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0); 1445 } 1446 1447 return array($this->_normalize($quotient), $this->_normalize($remainder)); 1448 } 1449 1450 if (count($y->value) == 1) { 1451 list($q, $r) = $this->_divide_digit($this->value, $y->value[0]); 1452 $quotient = new static(); 1453 $remainder = new static(); 1454 $quotient->value = $q; 1455 $remainder->value = array($r); 1456 $quotient->is_negative = $this->is_negative != $y->is_negative; 1457 return array($this->_normalize($quotient), $this->_normalize($remainder)); 1458 } 1459 1460 static $zero; 1461 if (!isset($zero)) { 1462 $zero = new static(); 1463 } 1464 1465 $x = $this->copy(); 1466 $y = $y->copy(); 1467 1468 $x_sign = $x->is_negative; 1469 $y_sign = $y->is_negative; 1470 1471 $x->is_negative = $y->is_negative = false; 1472 1473 $diff = $x->compare($y); 1474 1475 if (!$diff) { 1476 $temp = new static(); 1477 $temp->value = array(1); 1478 $temp->is_negative = $x_sign != $y_sign; 1479 return array($this->_normalize($temp), $this->_normalize(new static())); 1480 } 1481 1482 if ($diff < 0) { 1483 // if $x is negative, "add" $y. 1484 if ($x_sign) { 1485 $x = $y->subtract($x); 1486 } 1487 return array($this->_normalize(new static()), $this->_normalize($x)); 1488 } 1489 1490 // normalize $x and $y as described in HAC 14.23 / 14.24 1491 $msb = $y->value[count($y->value) - 1]; 1492 for ($shift = 0; !($msb & self::$msb); ++$shift) { 1493 $msb <<= 1; 1494 } 1495 $x->_lshift($shift); 1496 $y->_lshift($shift); 1497 $y_value = &$y->value; 1498 1499 $x_max = count($x->value) - 1; 1500 $y_max = count($y->value) - 1; 1501 1502 $quotient = new static(); 1503 $quotient_value = &$quotient->value; 1504 $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1); 1505 1506 static $temp, $lhs, $rhs; 1507 if (!isset($temp)) { 1508 $temp = new static(); 1509 $lhs = new static(); 1510 $rhs = new static(); 1511 } 1512 $temp_value = &$temp->value; 1513 $rhs_value = &$rhs->value; 1514 1515 // $temp = $y << ($x_max - $y_max-1) in base 2**26 1516 $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value); 1517 1518 while ($x->compare($temp) >= 0) { 1519 // calculate the "common residue" 1520 ++$quotient_value[$x_max - $y_max]; 1521 $x = $x->subtract($temp); 1522 $x_max = count($x->value) - 1; 1523 } 1524 1525 for ($i = $x_max; $i >= $y_max + 1; --$i) { 1526 $x_value = &$x->value; 1527 $x_window = array( 1528 isset($x_value[$i]) ? $x_value[$i] : 0, 1529 isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, 1530 isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0 1531 ); 1532 $y_window = array( 1533 $y_value[$y_max], 1534 ($y_max > 0) ? $y_value[$y_max - 1] : 0 1535 ); 1536 1537 $q_index = $i - $y_max - 1; 1538 if ($x_window[0] == $y_window[0]) { 1539 $quotient_value[$q_index] = self::$maxDigit; 1540 } else { 1541 $quotient_value[$q_index] = $this->_safe_divide( 1542 $x_window[0] * self::$baseFull + $x_window[1], 1543 $y_window[0] 1544 ); 1545 } 1546 1547 $temp_value = array($y_window[1], $y_window[0]); 1548 1549 $lhs->value = array($quotient_value[$q_index]); 1550 $lhs = $lhs->multiply($temp); 1551 1552 $rhs_value = array($x_window[2], $x_window[1], $x_window[0]); 1553 1554 while ($lhs->compare($rhs) > 0) { 1555 --$quotient_value[$q_index]; 1556 1557 $lhs->value = array($quotient_value[$q_index]); 1558 $lhs = $lhs->multiply($temp); 1559 } 1560 1561 $adjust = $this->_array_repeat(0, $q_index); 1562 $temp_value = array($quotient_value[$q_index]); 1563 $temp = $temp->multiply($y); 1564 $temp_value = &$temp->value; 1565 if (count($temp_value)) { 1566 $temp_value = array_merge($adjust, $temp_value); 1567 } 1568 1569 $x = $x->subtract($temp); 1570 1571 if ($x->compare($zero) < 0) { 1572 $temp_value = array_merge($adjust, $y_value); 1573 $x = $x->add($temp); 1574 1575 --$quotient_value[$q_index]; 1576 } 1577 1578 $x_max = count($x_value) - 1; 1579 } 1580 1581 // unnormalize the remainder 1582 $x->_rshift($shift); 1583 1584 $quotient->is_negative = $x_sign != $y_sign; 1585 1586 // calculate the "common residue", if appropriate 1587 if ($x_sign) { 1588 $y->_rshift($shift); 1589 $x = $y->subtract($x); 1590 } 1591 1592 return array($this->_normalize($quotient), $this->_normalize($x)); 1593 } 1594 1595 /** 1596 * Divides a BigInteger by a regular integer 1597 * 1598 * abc / x = a00 / x + b0 / x + c / x 1599 * 1600 * @param array $dividend 1601 * @param array $divisor 1602 * @return array 1603 * @access private 1604 */ 1605 function _divide_digit($dividend, $divisor) 1606 { 1607 $carry = 0; 1608 $result = array(); 1609 1610 for ($i = count($dividend) - 1; $i >= 0; --$i) { 1611 $temp = self::$baseFull * $carry + $dividend[$i]; 1612 $result[$i] = $this->_safe_divide($temp, $divisor); 1613 $carry = (int) ($temp - $divisor * $result[$i]); 1614 } 1615 1616 return array($result, $carry); 1617 } 1618 1619 /** 1620 * Performs modular exponentiation. 1621 * 1622 * Here's an example: 1623 * <code> 1624 * <?php 1625 * $a = new \phpseclib\Math\BigInteger('10'); 1626 * $b = new \phpseclib\Math\BigInteger('20'); 1627 * $c = new \phpseclib\Math\BigInteger('30'); 1628 * 1629 * $c = $a->modPow($b, $c); 1630 * 1631 * echo $c->toString(); // outputs 10 1632 * ?> 1633 * </code> 1634 * 1635 * @param \phpseclib\Math\BigInteger $e 1636 * @param \phpseclib\Math\BigInteger $n 1637 * @return \phpseclib\Math\BigInteger 1638 * @access public 1639 * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and 1640 * and although the approach involving repeated squaring does vastly better, it, too, is impractical 1641 * for our purposes. The reason being that division - by far the most complicated and time-consuming 1642 * of the basic operations (eg. +,-,*,/) - occurs multiple times within it. 1643 * 1644 * Modular reductions resolve this issue. Although an individual modular reduction takes more time 1645 * then an individual division, when performed in succession (with the same modulo), they're a lot faster. 1646 * 1647 * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction, 1648 * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the 1649 * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because 1650 * the product of two odd numbers is odd), but what about when RSA isn't used? 1651 * 1652 * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a 1653 * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the 1654 * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however, 1655 * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and 1656 * the other, a power of two - and recombine them, later. This is the method that this modPow function uses. 1657 * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates. 1658 */ 1659 function modPow($e, $n) 1660 { 1661 $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs(); 1662 1663 if ($e->compare(new static()) < 0) { 1664 $e = $e->abs(); 1665 1666 $temp = $this->modInverse($n); 1667 if ($temp === false) { 1668 return false; 1669 } 1670 1671 return $this->_normalize($temp->modPow($e, $n)); 1672 } 1673 1674 if (MATH_BIGINTEGER_MODE == self::MODE_GMP) { 1675 $temp = new static(); 1676 $temp->value = gmp_powm($this->value, $e->value, $n->value); 1677 1678 return $this->_normalize($temp); 1679 } 1680 1681 if ($this->compare(new static()) < 0 || $this->compare($n) > 0) { 1682 list(, $temp) = $this->divide($n); 1683 return $temp->modPow($e, $n); 1684 } 1685 1686 if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { 1687 $components = array( 1688 'modulus' => $n->toBytes(true), 1689 'publicExponent' => $e->toBytes(true) 1690 ); 1691 1692 $components = array( 1693 'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']), 1694 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']) 1695 ); 1696 1697 $RSAPublicKey = pack( 1698 'Ca*a*a*', 1699 48, 1700 $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), 1701 $components['modulus'], 1702 $components['publicExponent'] 1703 ); 1704 1705 $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA 1706 $RSAPublicKey = chr(0) . $RSAPublicKey; 1707 $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; 1708 1709 $encapsulated = pack( 1710 'Ca*a*', 1711 48, 1712 $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), 1713 $rsaOID . $RSAPublicKey 1714 ); 1715 1716 $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . 1717 chunk_split(base64_encode($encapsulated)) . 1718 '-----END PUBLIC KEY-----'; 1719 1720 $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT); 1721 1722 if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) { 1723 return new static($result, 256); 1724 } 1725 } 1726 1727 if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { 1728 $temp = new static(); 1729 $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); 1730 1731 return $this->_normalize($temp); 1732 } 1733 1734 if (empty($e->value)) { 1735 $temp = new static(); 1736 $temp->value = array(1); 1737 return $this->_normalize($temp); 1738 } 1739 1740 if ($e->value == array(1)) { 1741 list(, $temp) = $this->divide($n); 1742 return $this->_normalize($temp); 1743 } 1744 1745 if ($e->value == array(2)) { 1746 $temp = new static(); 1747 $temp->value = $this->_square($this->value); 1748 list(, $temp) = $temp->divide($n); 1749 return $this->_normalize($temp); 1750 } 1751 1752 return $this->_normalize($this->_slidingWindow($e, $n, self::BARRETT)); 1753 1754 // the following code, although not callable, can be run independently of the above code 1755 // although the above code performed better in my benchmarks the following could might 1756 // perform better under different circumstances. in lieu of deleting it it's just been 1757 // made uncallable 1758 1759 // is the modulo odd? 1760 if ($n->value[0] & 1) { 1761 return $this->_normalize($this->_slidingWindow($e, $n, self::MONTGOMERY)); 1762 } 1763 // if it's not, it's even 1764 1765 // find the lowest set bit (eg. the max pow of 2 that divides $n) 1766 for ($i = 0; $i < count($n->value); ++$i) { 1767 if ($n->value[$i]) { 1768 $temp = decbin($n->value[$i]); 1769 $j = strlen($temp) - strrpos($temp, '1') - 1; 1770 $j+= 26 * $i; 1771 break; 1772 } 1773 } 1774 // at this point, 2^$j * $n/(2^$j) == $n 1775 1776 $mod1 = $n->copy(); 1777 $mod1->_rshift($j); 1778 $mod2 = new static(); 1779 $mod2->value = array(1); 1780 $mod2->_lshift($j); 1781 1782 $part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static(); 1783 $part2 = $this->_slidingWindow($e, $mod2, self::POWEROF2); 1784 1785 $y1 = $mod2->modInverse($mod1); 1786 $y2 = $mod1->modInverse($mod2); 1787 1788 $result = $part1->multiply($mod2); 1789 $result = $result->multiply($y1); 1790 1791 $temp = $part2->multiply($mod1); 1792 $temp = $temp->multiply($y2); 1793 1794 $result = $result->add($temp); 1795 list(, $result) = $result->divide($n); 1796 1797 return $this->_normalize($result); 1798 } 1799 1800 /** 1801 * Performs modular exponentiation. 1802 * 1803 * Alias for modPow(). 1804 * 1805 * @param \phpseclib\Math\BigInteger $e 1806 * @param \phpseclib\Math\BigInteger $n 1807 * @return \phpseclib\Math\BigInteger 1808 * @access public 1809 */ 1810 function powMod($e, $n) 1811 { 1812 return $this->modPow($e, $n); 1813 } 1814 1815 /** 1816 * Sliding Window k-ary Modular Exponentiation 1817 * 1818 * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} / 1819 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims, 1820 * however, this function performs a modular reduction after every multiplication and squaring operation. 1821 * As such, this function has the same preconditions that the reductions being used do. 1822 * 1823 * @param \phpseclib\Math\BigInteger $e 1824 * @param \phpseclib\Math\BigInteger $n 1825 * @param int $mode 1826 * @return \phpseclib\Math\BigInteger 1827 * @access private 1828 */ 1829 function _slidingWindow($e, $n, $mode) 1830 { 1831 static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function 1832 //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1 1833 1834 $e_value = $e->value; 1835 $e_length = count($e_value) - 1; 1836 $e_bits = decbin($e_value[$e_length]); 1837 for ($i = $e_length - 1; $i >= 0; --$i) { 1838 $e_bits.= str_pad(decbin($e_value[$i]), self::$base, '0', STR_PAD_LEFT); 1839 } 1840 1841 $e_length = strlen($e_bits); 1842 1843 // calculate the appropriate window size. 1844 // $window_size == 3 if $window_ranges is between 25 and 81, for example. 1845 for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) { 1846 } 1847 1848 $n_value = $n->value; 1849 1850 // precompute $this^0 through $this^$window_size 1851 $powers = array(); 1852 $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode); 1853 $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode); 1854 1855 // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end 1856 // in a 1. ie. it's supposed to be odd. 1857 $temp = 1 << ($window_size - 1); 1858 for ($i = 1; $i < $temp; ++$i) { 1859 $i2 = $i << 1; 1860 $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode); 1861 } 1862 1863 $result = array(1); 1864 $result = $this->_prepareReduce($result, $n_value, $mode); 1865 1866 for ($i = 0; $i < $e_length;) { 1867 if (!$e_bits[$i]) { 1868 $result = $this->_squareReduce($result, $n_value, $mode); 1869 ++$i; 1870 } else { 1871 for ($j = $window_size - 1; $j > 0; --$j) { 1872 if (!empty($e_bits[$i + $j])) { 1873 break; 1874 } 1875 } 1876 1877 // eg. the length of substr($e_bits, $i, $j + 1) 1878 for ($k = 0; $k <= $j; ++$k) { 1879 $result = $this->_squareReduce($result, $n_value, $mode); 1880 } 1881 1882 $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode); 1883 1884 $i += $j + 1; 1885 } 1886 } 1887 1888 $temp = new static(); 1889 $temp->value = $this->_reduce($result, $n_value, $mode); 1890 1891 return $temp; 1892 } 1893 1894 /** 1895 * Modular reduction 1896 * 1897 * For most $modes this will return the remainder. 1898 * 1899 * @see self::_slidingWindow() 1900 * @access private 1901 * @param array $x 1902 * @param array $n 1903 * @param int $mode 1904 * @return array 1905 */ 1906 function _reduce($x, $n, $mode) 1907 { 1908 switch ($mode) { 1909 case self::MONTGOMERY: 1910 return $this->_montgomery($x, $n); 1911 case self::BARRETT: 1912 return $this->_barrett($x, $n); 1913 case self::POWEROF2: 1914 $lhs = new static(); 1915 $lhs->value = $x; 1916 $rhs = new static(); 1917 $rhs->value = $n; 1918 return $x->_mod2($n); 1919 case self::CLASSIC: 1920 $lhs = new static(); 1921 $lhs->value = $x; 1922 $rhs = new static(); 1923 $rhs->value = $n; 1924 list(, $temp) = $lhs->divide($rhs); 1925 return $temp->value; 1926 case self::NONE: 1927 return $x; 1928 default: 1929 // an invalid $mode was provided 1930 } 1931 } 1932 1933 /** 1934 * Modular reduction preperation 1935 * 1936 * @see self::_slidingWindow() 1937 * @access private 1938 * @param array $x 1939 * @param array $n 1940 * @param int $mode 1941 * @return array 1942 */ 1943 function _prepareReduce($x, $n, $mode) 1944 { 1945 if ($mode == self::MONTGOMERY) { 1946 return $this->_prepMontgomery($x, $n); 1947 } 1948 return $this->_reduce($x, $n, $mode); 1949 } 1950 1951 /** 1952 * Modular multiply 1953 * 1954 * @see self::_slidingWindow() 1955 * @access private 1956 * @param array $x 1957 * @param array $y 1958 * @param array $n 1959 * @param int $mode 1960 * @return array 1961 */ 1962 function _multiplyReduce($x, $y, $n, $mode) 1963 { 1964 if ($mode == self::MONTGOMERY) { 1965 return $this->_montgomeryMultiply($x, $y, $n); 1966 } 1967 $temp = $this->_multiply($x, false, $y, false); 1968 return $this->_reduce($temp[self::VALUE], $n, $mode); 1969 } 1970 1971 /** 1972 * Modular square 1973 * 1974 * @see self::_slidingWindow() 1975 * @access private 1976 * @param array $x 1977 * @param array $n 1978 * @param int $mode 1979 * @return array 1980 */ 1981 function _squareReduce($x, $n, $mode) 1982 { 1983 if ($mode == self::MONTGOMERY) { 1984 return $this->_montgomeryMultiply($x, $x, $n); 1985 } 1986 return $this->_reduce($this->_square($x), $n, $mode); 1987 } 1988 1989 /** 1990 * Modulos for Powers of Two 1991 * 1992 * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1), 1993 * we'll just use this function as a wrapper for doing that. 1994 * 1995 * @see self::_slidingWindow() 1996 * @access private 1997 * @param \phpseclib\Math\BigInteger 1998 * @return \phpseclib\Math\BigInteger 1999 */ 2000 function _mod2($n) 2001 { 2002 $temp = new static(); 2003 $temp->value = array(1); 2004 return $this->bitwise_and($n->subtract($temp)); 2005 } 2006 2007 /** 2008 * Barrett Modular Reduction 2009 * 2010 * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / 2011 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, 2012 * so as not to require negative numbers (initially, this script didn't support negative numbers). 2013 * 2014 * Employs "folding", as described at 2015 * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from 2016 * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x." 2017 * 2018 * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that 2019 * usable on account of (1) its not using reasonable radix points as discussed in 2020 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable 2021 * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that 2022 * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line 2023 * comments for details. 2024 * 2025 * @see self::_slidingWindow() 2026 * @access private 2027 * @param array $n 2028 * @param array $m 2029 * @return array 2030 */ 2031 function _barrett($n, $m) 2032 { 2033 static $cache = array( 2034 self::VARIABLE => array(), 2035 self::DATA => array() 2036 ); 2037 2038 $m_length = count($m); 2039 2040 // if ($this->_compare($n, $this->_square($m)) >= 0) { 2041 if (count($n) > 2 * $m_length) { 2042 $lhs = new static(); 2043 $rhs = new static(); 2044 $lhs->value = $n; 2045 $rhs->value = $m; 2046 list(, $temp) = $lhs->divide($rhs); 2047 return $temp->value; 2048 } 2049 2050 // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced 2051 if ($m_length < 5) { 2052 return $this->_regularBarrett($n, $m); 2053 } 2054 2055 // n = 2 * m.length 2056 2057 if (($key = array_search($m, $cache[self::VARIABLE])) === false) { 2058 $key = count($cache[self::VARIABLE]); 2059 $cache[self::VARIABLE][] = $m; 2060 2061 $lhs = new static(); 2062 $lhs_value = &$lhs->value; 2063 $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1)); 2064 $lhs_value[] = 1; 2065 $rhs = new static(); 2066 $rhs->value = $m; 2067 2068 list($u, $m1) = $lhs->divide($rhs); 2069 $u = $u->value; 2070 $m1 = $m1->value; 2071 2072 $cache[self::DATA][] = array( 2073 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1) 2074 'm1'=> $m1 // m.length 2075 ); 2076 } else { 2077 extract($cache[self::DATA][$key]); 2078 } 2079 2080 $cutoff = $m_length + ($m_length >> 1); 2081 $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1) 2082 $msd = array_slice($n, $cutoff); // m.length >> 1 2083 $lsd = $this->_trim($lsd); 2084 $temp = $this->_multiply($msd, false, $m1, false); 2085 $n = $this->_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1 2086 2087 if ($m_length & 1) { 2088 return $this->_regularBarrett($n[self::VALUE], $m); 2089 } 2090 2091 // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2 2092 $temp = array_slice($n[self::VALUE], $m_length - 1); 2093 // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 2094 // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 2095 $temp = $this->_multiply($temp, false, $u, false); 2096 // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 2097 // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) 2098 $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1); 2099 // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 2100 // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) 2101 $temp = $this->_multiply($temp, false, $m, false); 2102 2103 // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit 2104 // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop 2105 // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). 2106 2107 $result = $this->_subtract($n[self::VALUE], false, $temp[self::VALUE], false); 2108 2109 while ($this->_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) { 2110 $result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $m, false); 2111 } 2112 2113 return $result[self::VALUE]; 2114 } 2115 2116 /** 2117 * (Regular) Barrett Modular Reduction 2118 * 2119 * For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this 2120 * is that this function does not fold the denominator into a smaller form. 2121 * 2122 * @see self::_slidingWindow() 2123 * @access private 2124 * @param array $x 2125 * @param array $n 2126 * @return array 2127 */ 2128 function _regularBarrett($x, $n) 2129 { 2130 static $cache = array( 2131 self::VARIABLE => array(), 2132 self::DATA => array() 2133 ); 2134 2135 $n_length = count($n); 2136 2137 if (count($x) > 2 * $n_length) { 2138 $lhs = new static(); 2139 $rhs = new static(); 2140 $lhs->value = $x; 2141 $rhs->value = $n; 2142 list(, $temp) = $lhs->divide($rhs); 2143 return $temp->value; 2144 } 2145 2146 if (($key = array_search($n, $cache[self::VARIABLE])) === false) { 2147 $key = count($cache[self::VARIABLE]); 2148 $cache[self::VARIABLE][] = $n; 2149 $lhs = new static(); 2150 $lhs_value = &$lhs->value; 2151 $lhs_value = $this->_array_repeat(0, 2 * $n_length); 2152 $lhs_value[] = 1; 2153 $rhs = new static(); 2154 $rhs->value = $n; 2155 list($temp, ) = $lhs->divide($rhs); // m.length 2156 $cache[self::DATA][] = $temp->value; 2157 } 2158 2159 // 2 * m.length - (m.length - 1) = m.length + 1 2160 $temp = array_slice($x, $n_length - 1); 2161 // (m.length + 1) + m.length = 2 * m.length + 1 2162 $temp = $this->_multiply($temp, false, $cache[self::DATA][$key], false); 2163 // (2 * m.length + 1) - (m.length - 1) = m.length + 2 2164 $temp = array_slice($temp[self::VALUE], $n_length + 1); 2165 2166 // m.length + 1 2167 $result = array_slice($x, 0, $n_length + 1); 2168 // m.length + 1 2169 $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1); 2170 // $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1) 2171 2172 if ($this->_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) { 2173 $corrector_value = $this->_array_repeat(0, $n_length + 1); 2174 $corrector_value[count($corrector_value)] = 1; 2175 $result = $this->_add($result, false, $corrector_value, false); 2176 $result = $result[self::VALUE]; 2177 } 2178 2179 // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits 2180 $result = $this->_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]); 2181 while ($this->_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) { 2182 $result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $n, false); 2183 } 2184 2185 return $result[self::VALUE]; 2186 } 2187 2188 /** 2189 * Performs long multiplication up to $stop digits 2190 * 2191 * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved. 2192 * 2193 * @see self::_regularBarrett() 2194 * @param array $x_value 2195 * @param bool $x_negative 2196 * @param array $y_value 2197 * @param bool $y_negative 2198 * @param int $stop 2199 * @return array 2200 * @access private 2201 */ 2202 function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop) 2203 { 2204 $x_length = count($x_value); 2205 $y_length = count($y_value); 2206 2207 if (!$x_length || !$y_length) { // a 0 is being multiplied 2208 return array( 2209 self::VALUE => array(), 2210 self::SIGN => false 2211 ); 2212 } 2213 2214 if ($x_length < $y_length) { 2215 $temp = $x_value; 2216 $x_value = $y_value; 2217 $y_value = $temp; 2218 2219 $x_length = count($x_value); 2220 $y_length = count($y_value); 2221 } 2222 2223 $product_value = $this->_array_repeat(0, $x_length + $y_length); 2224 2225 // the following for loop could be removed if the for loop following it 2226 // (the one with nested for loops) initially set $i to 0, but 2227 // doing so would also make the result in one set of unnecessary adds, 2228 // since on the outermost loops first pass, $product->value[$k] is going 2229 // to always be 0 2230 2231 $carry = 0; 2232 2233 for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i 2234 $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 2235 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 2236 $product_value[$j] = (int) ($temp - self::$baseFull * $carry); 2237 } 2238 2239 if ($j < $stop) { 2240 $product_value[$j] = $carry; 2241 } 2242 2243 // the above for loop is what the previous comment was talking about. the 2244 // following for loop is the "one with nested for loops" 2245 2246 for ($i = 1; $i < $y_length; ++$i) { 2247 $carry = 0; 2248 2249 for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) { 2250 $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; 2251 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 2252 $product_value[$k] = (int) ($temp - self::$baseFull * $carry); 2253 } 2254 2255 if ($k < $stop) { 2256 $product_value[$k] = $carry; 2257 } 2258 } 2259 2260 return array( 2261 self::VALUE => $this->_trim($product_value), 2262 self::SIGN => $x_negative != $y_negative 2263 ); 2264 } 2265 2266 /** 2267 * Montgomery Modular Reduction 2268 * 2269 * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n. 2270 * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be 2271 * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function 2272 * to work correctly. 2273 * 2274 * @see self::_prepMontgomery() 2275 * @see self::_slidingWindow() 2276 * @access private 2277 * @param array $x 2278 * @param array $n 2279 * @return array 2280 */ 2281 function _montgomery($x, $n) 2282 { 2283 static $cache = array( 2284 self::VARIABLE => array(), 2285 self::DATA => array() 2286 ); 2287 2288 if (($key = array_search($n, $cache[self::VARIABLE])) === false) { 2289 $key = count($cache[self::VARIABLE]); 2290 $cache[self::VARIABLE][] = $x; 2291 $cache[self::DATA][] = $this->_modInverse67108864($n); 2292 } 2293 2294 $k = count($n); 2295 2296 $result = array(self::VALUE => $x); 2297 2298 for ($i = 0; $i < $k; ++$i) { 2299 $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key]; 2300 $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); 2301 $temp = $this->_regularMultiply(array($temp), $n); 2302 $temp = array_merge($this->_array_repeat(0, $i), $temp); 2303 $result = $this->_add($result[self::VALUE], false, $temp, false); 2304 } 2305 2306 $result[self::VALUE] = array_slice($result[self::VALUE], $k); 2307 2308 if ($this->_compare($result, false, $n, false) >= 0) { 2309 $result = $this->_subtract($result[self::VALUE], false, $n, false); 2310 } 2311 2312 return $result[self::VALUE]; 2313 } 2314 2315 /** 2316 * Montgomery Multiply 2317 * 2318 * Interleaves the montgomery reduction and long multiplication algorithms together as described in 2319 * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} 2320 * 2321 * @see self::_prepMontgomery() 2322 * @see self::_montgomery() 2323 * @access private 2324 * @param array $x 2325 * @param array $y 2326 * @param array $m 2327 * @return array 2328 */ 2329 function _montgomeryMultiply($x, $y, $m) 2330 { 2331 $temp = $this->_multiply($x, false, $y, false); 2332 return $this->_montgomery($temp[self::VALUE], $m); 2333 2334 // the following code, although not callable, can be run independently of the above code 2335 // although the above code performed better in my benchmarks the following could might 2336 // perform better under different circumstances. in lieu of deleting it it's just been 2337 // made uncallable 2338 2339 static $cache = array( 2340 self::VARIABLE => array(), 2341 self::DATA => array() 2342 ); 2343 2344 if (($key = array_search($m, $cache[self::VARIABLE])) === false) { 2345 $key = count($cache[self::VARIABLE]); 2346 $cache[self::VARIABLE][] = $m; 2347 $cache[self::DATA][] = $this->_modInverse67108864($m); 2348 } 2349 2350 $n = max(count($x), count($y), count($m)); 2351 $x = array_pad($x, $n, 0); 2352 $y = array_pad($y, $n, 0); 2353 $m = array_pad($m, $n, 0); 2354 $a = array(self::VALUE => $this->_array_repeat(0, $n + 1)); 2355 for ($i = 0; $i < $n; ++$i) { 2356 $temp = $a[self::VALUE][0] + $x[$i] * $y[0]; 2357 $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); 2358 $temp = $temp * $cache[self::DATA][$key]; 2359 $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); 2360 $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false); 2361 $a = $this->_add($a[self::VALUE], false, $temp[self::VALUE], false); 2362 $a[self::VALUE] = array_slice($a[self::VALUE], 1); 2363 } 2364 if ($this->_compare($a[self::VALUE], false, $m, false) >= 0) { 2365 $a = $this->_subtract($a[self::VALUE], false, $m, false); 2366 } 2367 return $a[self::VALUE]; 2368 } 2369 2370 /** 2371 * Prepare a number for use in Montgomery Modular Reductions 2372 * 2373 * @see self::_montgomery() 2374 * @see self::_slidingWindow() 2375 * @access private 2376 * @param array $x 2377 * @param array $n 2378 * @return array 2379 */ 2380 function _prepMontgomery($x, $n) 2381 { 2382 $lhs = new static(); 2383 $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x); 2384 $rhs = new static(); 2385 $rhs->value = $n; 2386 2387 list(, $temp) = $lhs->divide($rhs); 2388 return $temp->value; 2389 } 2390 2391 /** 2392 * Modular Inverse of a number mod 2**26 (eg. 67108864) 2393 * 2394 * Based off of the bnpInvDigit function implemented and justified in the following URL: 2395 * 2396 * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js} 2397 * 2398 * The following URL provides more info: 2399 * 2400 * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85} 2401 * 2402 * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For 2403 * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields 2404 * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't 2405 * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that 2406 * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the 2407 * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to 2408 * 40 bits, which only 64-bit floating points will support. 2409 * 2410 * Thanks to Pedro Gimeno Fortea for input! 2411 * 2412 * @see self::_montgomery() 2413 * @access private 2414 * @param array $x 2415 * @return int 2416 */ 2417 function _modInverse67108864($x) // 2**26 == 67,108,864 2418 { 2419 $x = -$x[0]; 2420 $result = $x & 0x3; // x**-1 mod 2**2 2421 $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4 2422 $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8 2423 $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16 2424 $result = fmod($result * (2 - fmod($x * $result, self::$baseFull)), self::$baseFull); // x**-1 mod 2**26 2425 return $result & self::$maxDigit; 2426 } 2427 2428 /** 2429 * Calculates modular inverses. 2430 * 2431 * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. 2432 * 2433 * Here's an example: 2434 * <code> 2435 * <?php 2436 * $a = new \phpseclib\Math\BigInteger(30); 2437 * $b = new \phpseclib\Math\BigInteger(17); 2438 * 2439 * $c = $a->modInverse($b); 2440 * echo $c->toString(); // outputs 4 2441 * 2442 * echo "\r\n"; 2443 * 2444 * $d = $a->multiply($c); 2445 * list(, $d) = $d->divide($b); 2446 * echo $d; // outputs 1 (as per the definition of modular inverse) 2447 * ?> 2448 * </code> 2449 * 2450 * @param \phpseclib\Math\BigInteger $n 2451 * @return \phpseclib\Math\BigInteger|false 2452 * @access public 2453 * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information. 2454 */ 2455 function modInverse($n) 2456 { 2457 switch (MATH_BIGINTEGER_MODE) { 2458 case self::MODE_GMP: 2459 $temp = new static(); 2460 $temp->value = gmp_invert($this->value, $n->value); 2461 2462 return ($temp->value === false) ? false : $this->_normalize($temp); 2463 } 2464 2465 static $zero, $one; 2466 if (!isset($zero)) { 2467 $zero = new static(); 2468 $one = new static(1); 2469 } 2470 2471 // $x mod -$n == $x mod $n. 2472 $n = $n->abs(); 2473 2474 if ($this->compare($zero) < 0) { 2475 $temp = $this->abs(); 2476 $temp = $temp->modInverse($n); 2477 return $this->_normalize($n->subtract($temp)); 2478 } 2479 2480 extract($this->extendedGCD($n)); 2481 2482 if (!$gcd->equals($one)) { 2483 return false; 2484 } 2485 2486 $x = $x->compare($zero) < 0 ? $x->add($n) : $x; 2487 2488 return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x); 2489 } 2490 2491 /** 2492 * Calculates the greatest common divisor and Bezout's identity. 2493 * 2494 * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that 2495 * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which 2496 * combination is returned is dependent upon which mode is in use. See 2497 * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information. 2498 * 2499 * Here's an example: 2500 * <code> 2501 * <?php 2502 * $a = new \phpseclib\Math\BigInteger(693); 2503 * $b = new \phpseclib\Math\BigInteger(609); 2504 * 2505 * extract($a->extendedGCD($b)); 2506 * 2507 * echo $gcd->toString() . "\r\n"; // outputs 21 2508 * echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21 2509 * ?> 2510 * </code> 2511 * 2512 * @param \phpseclib\Math\BigInteger $n 2513 * @return \phpseclib\Math\BigInteger 2514 * @access public 2515 * @internal Calculates the GCD using the binary xGCD algorithim described in 2516 * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes, 2517 * the more traditional algorithim requires "relatively costly multiple-precision divisions". 2518 */ 2519 function extendedGCD($n) 2520 { 2521 switch (MATH_BIGINTEGER_MODE) { 2522 case self::MODE_GMP: 2523 extract(gmp_gcdext($this->value, $n->value)); 2524 2525 return array( 2526 'gcd' => $this->_normalize(new static($g)), 2527 'x' => $this->_normalize(new static($s)), 2528 'y' => $this->_normalize(new static($t)) 2529 ); 2530 case self::MODE_BCMATH: 2531 // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works 2532 // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is, 2533 // the basic extended euclidean algorithim is what we're using. 2534 2535 $u = $this->value; 2536 $v = $n->value; 2537 2538 $a = '1'; 2539 $b = '0'; 2540 $c = '0'; 2541 $d = '1'; 2542 2543 while (bccomp($v, '0', 0) != 0) { 2544 $q = bcdiv($u, $v, 0); 2545 2546 $temp = $u; 2547 $u = $v; 2548 $v = bcsub($temp, bcmul($v, $q, 0), 0); 2549 2550 $temp = $a; 2551 $a = $c; 2552 $c = bcsub($temp, bcmul($a, $q, 0), 0); 2553 2554 $temp = $b; 2555 $b = $d; 2556 $d = bcsub($temp, bcmul($b, $q, 0), 0); 2557 } 2558 2559 return array( 2560 'gcd' => $this->_normalize(new static($u)), 2561 'x' => $this->_normalize(new static($a)), 2562 'y' => $this->_normalize(new static($b)) 2563 ); 2564 } 2565 2566 $y = $n->copy(); 2567 $x = $this->copy(); 2568 $g = new static(); 2569 $g->value = array(1); 2570 2571 while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) { 2572 $x->_rshift(1); 2573 $y->_rshift(1); 2574 $g->_lshift(1); 2575 } 2576 2577 $u = $x->copy(); 2578 $v = $y->copy(); 2579 2580 $a = new static(); 2581 $b = new static(); 2582 $c = new static(); 2583 $d = new static(); 2584 2585 $a->value = $d->value = $g->value = array(1); 2586 $b->value = $c->value = array(); 2587 2588 while (!empty($u->value)) { 2589 while (!($u->value[0] & 1)) { 2590 $u->_rshift(1); 2591 if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) { 2592 $a = $a->add($y); 2593 $b = $b->subtract($x); 2594 } 2595 $a->_rshift(1); 2596 $b->_rshift(1); 2597 } 2598 2599 while (!($v->value[0] & 1)) { 2600 $v->_rshift(1); 2601 if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) { 2602 $c = $c->add($y); 2603 $d = $d->subtract($x); 2604 } 2605 $c->_rshift(1); 2606 $d->_rshift(1); 2607 } 2608 2609 if ($u->compare($v) >= 0) { 2610 $u = $u->subtract($v); 2611 $a = $a->subtract($c); 2612 $b = $b->subtract($d); 2613 } else { 2614 $v = $v->subtract($u); 2615 $c = $c->subtract($a); 2616 $d = $d->subtract($b); 2617 } 2618 } 2619 2620 return array( 2621 'gcd' => $this->_normalize($g->multiply($v)), 2622 'x' => $this->_normalize($c), 2623 'y' => $this->_normalize($d) 2624 ); 2625 } 2626 2627 /** 2628 * Calculates the greatest common divisor 2629 * 2630 * Say you have 693 and 609. The GCD is 21. 2631 * 2632 * Here's an example: 2633 * <code> 2634 * <?php 2635 * $a = new \phpseclib\Math\BigInteger(693); 2636 * $b = new \phpseclib\Math\BigInteger(609); 2637 * 2638 * $gcd = a->extendedGCD($b); 2639 * 2640 * echo $gcd->toString() . "\r\n"; // outputs 21 2641 * ?> 2642 * </code> 2643 * 2644 * @param \phpseclib\Math\BigInteger $n 2645 * @return \phpseclib\Math\BigInteger 2646 * @access public 2647 */ 2648 function gcd($n) 2649 { 2650 extract($this->extendedGCD($n)); 2651 return $gcd; 2652 } 2653 2654 /** 2655 * Absolute value. 2656 * 2657 * @return \phpseclib\Math\BigInteger 2658 * @access public 2659 */ 2660 function abs() 2661 { 2662 $temp = new static(); 2663 2664 switch (MATH_BIGINTEGER_MODE) { 2665 case self::MODE_GMP: 2666 $temp->value = gmp_abs($this->value); 2667 break; 2668 case self::MODE_BCMATH: 2669 $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value; 2670 break; 2671 default: 2672 $temp->value = $this->value; 2673 } 2674 2675 return $temp; 2676 } 2677 2678 /** 2679 * Compares two numbers. 2680 * 2681 * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is 2682 * demonstrated thusly: 2683 * 2684 * $x > $y: $x->compare($y) > 0 2685 * $x < $y: $x->compare($y) < 0 2686 * $x == $y: $x->compare($y) == 0 2687 * 2688 * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). 2689 * 2690 * @param \phpseclib\Math\BigInteger $y 2691 * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. 2692 * @access public 2693 * @see self::equals() 2694 * @internal Could return $this->subtract($x), but that's not as fast as what we do do. 2695 */ 2696 function compare($y) 2697 { 2698 switch (MATH_BIGINTEGER_MODE) { 2699 case self::MODE_GMP: 2700 $r = gmp_cmp($this->value, $y->value); 2701 if ($r < -1) { 2702 $r = -1; 2703 } 2704 if ($r > 1) { 2705 $r = 1; 2706 } 2707 return $r; 2708 case self::MODE_BCMATH: 2709 return bccomp($this->value, $y->value, 0); 2710 } 2711 2712 return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative); 2713 } 2714 2715 /** 2716 * Compares two numbers. 2717 * 2718 * @param array $x_value 2719 * @param bool $x_negative 2720 * @param array $y_value 2721 * @param bool $y_negative 2722 * @return int 2723 * @see self::compare() 2724 * @access private 2725 */ 2726 function _compare($x_value, $x_negative, $y_value, $y_negative) 2727 { 2728 if ($x_negative != $y_negative) { 2729 return (!$x_negative && $y_negative) ? 1 : -1; 2730 } 2731 2732 $result = $x_negative ? -1 : 1; 2733 2734 if (count($x_value) != count($y_value)) { 2735 return (count($x_value) > count($y_value)) ? $result : -$result; 2736 } 2737 $size = max(count($x_value), count($y_value)); 2738 2739 $x_value = array_pad($x_value, $size, 0); 2740 $y_value = array_pad($y_value, $size, 0); 2741 2742 for ($i = count($x_value) - 1; $i >= 0; --$i) { 2743 if ($x_value[$i] != $y_value[$i]) { 2744 return ($x_value[$i] > $y_value[$i]) ? $result : -$result; 2745 } 2746 } 2747 2748 return 0; 2749 } 2750 2751 /** 2752 * Tests the equality of two numbers. 2753 * 2754 * If you need to see if one number is greater than or less than another number, use BigInteger::compare() 2755 * 2756 * @param \phpseclib\Math\BigInteger $x 2757 * @return bool 2758 * @access public 2759 * @see self::compare() 2760 */ 2761 function equals($x) 2762 { 2763 switch (MATH_BIGINTEGER_MODE) { 2764 case self::MODE_GMP: 2765 return gmp_cmp($this->value, $x->value) == 0; 2766 default: 2767 return $this->value === $x->value && $this->is_negative == $x->is_negative; 2768 } 2769 } 2770 2771 /** 2772 * Set Precision 2773 * 2774 * Some bitwise operations give different results depending on the precision being used. Examples include left 2775 * shift, not, and rotates. 2776 * 2777 * @param int $bits 2778 * @access public 2779 */ 2780 function setPrecision($bits) 2781 { 2782 $this->precision = $bits; 2783 if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) { 2784 $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); 2785 } else { 2786 $this->bitmask = new static(bcpow('2', $bits, 0)); 2787 } 2788 2789 $temp = $this->_normalize($this); 2790 $this->value = $temp->value; 2791 } 2792 2793 /** 2794 * Logical And 2795 * 2796 * @param \phpseclib\Math\BigInteger $x 2797 * @access public 2798 * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat> 2799 * @return \phpseclib\Math\BigInteger 2800 */ 2801 function bitwise_and($x) 2802 { 2803 switch (MATH_BIGINTEGER_MODE) { 2804 case self::MODE_GMP: 2805 $temp = new static(); 2806 $temp->value = gmp_and($this->value, $x->value); 2807 2808 return $this->_normalize($temp); 2809 case self::MODE_BCMATH: 2810 $left = $this->toBytes(); 2811 $right = $x->toBytes(); 2812 2813 $length = max(strlen($left), strlen($right)); 2814 2815 $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); 2816 $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); 2817 2818 return $this->_normalize(new static($left & $right, 256)); 2819 } 2820 2821 $result = $this->copy(); 2822 2823 $length = min(count($x->value), count($this->value)); 2824 2825 $result->value = array_slice($result->value, 0, $length); 2826 2827 for ($i = 0; $i < $length; ++$i) { 2828 $result->value[$i]&= $x->value[$i]; 2829 } 2830 2831 return $this->_normalize($result); 2832 } 2833 2834 /** 2835 * Logical Or 2836 * 2837 * @param \phpseclib\Math\BigInteger $x 2838 * @access public 2839 * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat> 2840 * @return \phpseclib\Math\BigInteger 2841 */ 2842 function bitwise_or($x) 2843 { 2844 switch (MATH_BIGINTEGER_MODE) { 2845 case self::MODE_GMP: 2846 $temp = new static(); 2847 $temp->value = gmp_or($this->value, $x->value); 2848 2849 return $this->_normalize($temp); 2850 case self::MODE_BCMATH: 2851 $left = $this->toBytes(); 2852 $right = $x->toBytes(); 2853 2854 $length = max(strlen($left), strlen($right)); 2855 2856 $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); 2857 $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); 2858 2859 return $this->_normalize(new static($left | $right, 256)); 2860 } 2861 2862 $length = max(count($this->value), count($x->value)); 2863 $result = $this->copy(); 2864 $result->value = array_pad($result->value, $length, 0); 2865 $x->value = array_pad($x->value, $length, 0); 2866 2867 for ($i = 0; $i < $length; ++$i) { 2868 $result->value[$i]|= $x->value[$i]; 2869 } 2870 2871 return $this->_normalize($result); 2872 } 2873 2874 /** 2875 * Logical Exclusive-Or 2876 * 2877 * @param \phpseclib\Math\BigInteger $x 2878 * @access public 2879 * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat> 2880 * @return \phpseclib\Math\BigInteger 2881 */ 2882 function bitwise_xor($x) 2883 { 2884 switch (MATH_BIGINTEGER_MODE) { 2885 case self::MODE_GMP: 2886 $temp = new static(); 2887 $temp->value = gmp_xor(gmp_abs($this->value), gmp_abs($x->value)); 2888 return $this->_normalize($temp); 2889 case self::MODE_BCMATH: 2890 $left = $this->toBytes(); 2891 $right = $x->toBytes(); 2892 2893 $length = max(strlen($left), strlen($right)); 2894 2895 $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); 2896 $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); 2897 2898 return $this->_normalize(new static($left ^ $right, 256)); 2899 } 2900 2901 $length = max(count($this->value), count($x->value)); 2902 $result = $this->copy(); 2903 $result->is_negative = false; 2904 $result->value = array_pad($result->value, $length, 0); 2905 $x->value = array_pad($x->value, $length, 0); 2906 2907 for ($i = 0; $i < $length; ++$i) { 2908 $result->value[$i]^= $x->value[$i]; 2909 } 2910 2911 return $this->_normalize($result); 2912 } 2913 2914 /** 2915 * Logical Not 2916 * 2917 * @access public 2918 * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat> 2919 * @return \phpseclib\Math\BigInteger 2920 */ 2921 function bitwise_not() 2922 { 2923 // calculuate "not" without regard to $this->precision 2924 // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0) 2925 $temp = $this->toBytes(); 2926 if ($temp == '') { 2927 return $this->_normalize(new static()); 2928 } 2929 $pre_msb = decbin(ord($temp[0])); 2930 $temp = ~$temp; 2931 $msb = decbin(ord($temp[0])); 2932 if (strlen($msb) == 8) { 2933 $msb = substr($msb, strpos($msb, '0')); 2934 } 2935 $temp[0] = chr(bindec($msb)); 2936 2937 // see if we need to add extra leading 1's 2938 $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8; 2939 $new_bits = $this->precision - $current_bits; 2940 if ($new_bits <= 0) { 2941 return $this->_normalize(new static($temp, 256)); 2942 } 2943 2944 // generate as many leading 1's as we need to. 2945 $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3); 2946 $this->_base256_lshift($leading_ones, $current_bits); 2947 2948 $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT); 2949 2950 return $this->_normalize(new static($leading_ones | $temp, 256)); 2951 } 2952 2953 /** 2954 * Logical Right Shift 2955 * 2956 * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. 2957 * 2958 * @param int $shift 2959 * @return \phpseclib\Math\BigInteger 2960 * @access public 2961 * @internal The only version that yields any speed increases is the internal version. 2962 */ 2963 function bitwise_rightShift($shift) 2964 { 2965 $temp = new static(); 2966 2967 switch (MATH_BIGINTEGER_MODE) { 2968 case self::MODE_GMP: 2969 static $two; 2970 2971 if (!isset($two)) { 2972 $two = gmp_init('2'); 2973 } 2974 2975 $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift)); 2976 2977 break; 2978 case self::MODE_BCMATH: 2979 $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0); 2980 2981 break; 2982 default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten 2983 // and I don't want to do that... 2984 $temp->value = $this->value; 2985 $temp->_rshift($shift); 2986 } 2987 2988 return $this->_normalize($temp); 2989 } 2990 2991 /** 2992 * Logical Left Shift 2993 * 2994 * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. 2995 * 2996 * @param int $shift 2997 * @return \phpseclib\Math\BigInteger 2998 * @access public 2999 * @internal The only version that yields any speed increases is the internal version. 3000 */ 3001 function bitwise_leftShift($shift) 3002 { 3003 $temp = new static(); 3004 3005 switch (MATH_BIGINTEGER_MODE) { 3006 case self::MODE_GMP: 3007 static $two; 3008 3009 if (!isset($two)) { 3010 $two = gmp_init('2'); 3011 } 3012 3013 $temp->value = gmp_mul($this->value, gmp_pow($two, $shift)); 3014 3015 break; 3016 case self::MODE_BCMATH: 3017 $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0); 3018 3019 break; 3020 default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten 3021 // and I don't want to do that... 3022 $temp->value = $this->value; 3023 $temp->_lshift($shift); 3024 } 3025 3026 return $this->_normalize($temp); 3027 } 3028 3029 /** 3030 * Logical Left Rotate 3031 * 3032 * Instead of the top x bits being dropped they're appended to the shifted bit string. 3033 * 3034 * @param int $shift 3035 * @return \phpseclib\Math\BigInteger 3036 * @access public 3037 */ 3038 function bitwise_leftRotate($shift) 3039 { 3040 $bits = $this->toBytes(); 3041 3042 if ($this->precision > 0) { 3043 $precision = $this->precision; 3044 if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { 3045 $mask = $this->bitmask->subtract(new static(1)); 3046 $mask = $mask->toBytes(); 3047 } else { 3048 $mask = $this->bitmask->toBytes(); 3049 } 3050 } else { 3051 $temp = ord($bits[0]); 3052 for ($i = 0; $temp >> $i; ++$i) { 3053 } 3054 $precision = 8 * strlen($bits) - 8 + $i; 3055 $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); 3056 } 3057 3058 if ($shift < 0) { 3059 $shift+= $precision; 3060 } 3061 $shift%= $precision; 3062 3063 if (!$shift) { 3064 return $this->copy(); 3065 } 3066 3067 $left = $this->bitwise_leftShift($shift); 3068 $left = $left->bitwise_and(new static($mask, 256)); 3069 $right = $this->bitwise_rightShift($precision - $shift); 3070 $result = MATH_BIGINTEGER_MODE != self::MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right); 3071 return $this->_normalize($result); 3072 } 3073 3074 /** 3075 * Logical Right Rotate 3076 * 3077 * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. 3078 * 3079 * @param int $shift 3080 * @return \phpseclib\Math\BigInteger 3081 * @access public 3082 */ 3083 function bitwise_rightRotate($shift) 3084 { 3085 return $this->bitwise_leftRotate(-$shift); 3086 } 3087 3088 /** 3089 * Generates a random BigInteger 3090 * 3091 * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not. 3092 * 3093 * @param int $length 3094 * @return \phpseclib\Math\BigInteger 3095 * @access private 3096 */ 3097 function _random_number_helper($size) 3098 { 3099 if (class_exists('\phpseclib\Crypt\Random')) { 3100 $random = Random::string($size); 3101 } else { 3102 $random = ''; 3103 3104 if ($size & 1) { 3105 $random.= chr(mt_rand(0, 255)); 3106 } 3107 3108 $blocks = $size >> 1; 3109 for ($i = 0; $i < $blocks; ++$i) { 3110 // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems 3111 $random.= pack('n', mt_rand(0, 0xFFFF)); 3112 } 3113 } 3114 3115 return new static($random, 256); 3116 } 3117 3118 /** 3119 * Generate a random number 3120 * 3121 * Returns a random number between $min and $max where $min and $max 3122 * can be defined using one of the two methods: 3123 * 3124 * $min->random($max) 3125 * $max->random($min) 3126 * 3127 * @param \phpseclib\Math\BigInteger $arg1 3128 * @param \phpseclib\Math\BigInteger $arg2 3129 * @return \phpseclib\Math\BigInteger 3130 * @access public 3131 * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a BigInteger object. 3132 * That method is still supported for BC purposes. 3133 */ 3134 function random($arg1, $arg2 = false) 3135 { 3136 if ($arg1 === false) { 3137 return false; 3138 } 3139 3140 if ($arg2 === false) { 3141 $max = $arg1; 3142 $min = $this; 3143 } else { 3144 $min = $arg1; 3145 $max = $arg2; 3146 } 3147 3148 $compare = $max->compare($min); 3149 3150 if (!$compare) { 3151 return $this->_normalize($min); 3152 } elseif ($compare < 0) { 3153 // if $min is bigger then $max, swap $min and $max 3154 $temp = $max; 3155 $max = $min; 3156 $min = $temp; 3157 } 3158 3159 static $one; 3160 if (!isset($one)) { 3161 $one = new static(1); 3162 } 3163 3164 $max = $max->subtract($min->subtract($one)); 3165 $size = strlen(ltrim($max->toBytes(), chr(0))); 3166 3167 /* 3168 doing $random % $max doesn't work because some numbers will be more likely to occur than others. 3169 eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145 3170 would produce 5 whereas the only value of random that could produce 139 would be 139. ie. 3171 not all numbers would be equally likely. some would be more likely than others. 3172 3173 creating a whole new random number until you find one that is within the range doesn't work 3174 because, for sufficiently small ranges, the likelihood that you'd get a number within that range 3175 would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability 3176 would be pretty high that $random would be greater than $max. 3177 3178 phpseclib works around this using the technique described here: 3179 3180 http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string 3181 */ 3182 $random_max = new static(chr(1) . str_repeat("\0", $size), 256); 3183 $random = $this->_random_number_helper($size); 3184 3185 list($max_multiple) = $random_max->divide($max); 3186 $max_multiple = $max_multiple->multiply($max); 3187 3188 while ($random->compare($max_multiple) >= 0) { 3189 $random = $random->subtract($max_multiple); 3190 $random_max = $random_max->subtract($max_multiple); 3191 $random = $random->bitwise_leftShift(8); 3192 $random = $random->add($this->_random_number_helper(1)); 3193 $random_max = $random_max->bitwise_leftShift(8); 3194 list($max_multiple) = $random_max->divide($max); 3195 $max_multiple = $max_multiple->multiply($max); 3196 } 3197 list(, $random) = $random->divide($max); 3198 3199 return $this->_normalize($random->add($min)); 3200 } 3201 3202 /** 3203 * Generate a random prime number. 3204 * 3205 * If there's not a prime within the given range, false will be returned. 3206 * If more than $timeout seconds have elapsed, give up and return false. 3207 * 3208 * @param \phpseclib\Math\BigInteger $arg1 3209 * @param \phpseclib\Math\BigInteger $arg2 3210 * @param int $timeout 3211 * @return Math_BigInteger|false 3212 * @access public 3213 * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}. 3214 */ 3215 function randomPrime($arg1, $arg2 = false, $timeout = false) 3216 { 3217 if ($arg1 === false) { 3218 return false; 3219 } 3220 3221 if ($arg2 === false) { 3222 $max = $arg1; 3223 $min = $this; 3224 } else { 3225 $min = $arg1; 3226 $max = $arg2; 3227 } 3228 3229 $compare = $max->compare($min); 3230 3231 if (!$compare) { 3232 return $min->isPrime() ? $min : false; 3233 } elseif ($compare < 0) { 3234 // if $min is bigger then $max, swap $min and $max 3235 $temp = $max; 3236 $max = $min; 3237 $min = $temp; 3238 } 3239 3240 static $one, $two; 3241 if (!isset($one)) { 3242 $one = new static(1); 3243 $two = new static(2); 3244 } 3245 3246 $start = time(); 3247 3248 $x = $this->random($min, $max); 3249 3250 // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>. 3251 if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) { 3252 $p = new static(); 3253 $p->value = gmp_nextprime($x->value); 3254 3255 if ($p->compare($max) <= 0) { 3256 return $p; 3257 } 3258 3259 if (!$min->equals($x)) { 3260 $x = $x->subtract($one); 3261 } 3262 3263 return $x->randomPrime($min, $x); 3264 } 3265 3266 if ($x->equals($two)) { 3267 return $x; 3268 } 3269 3270 $x->_make_odd(); 3271 if ($x->compare($max) > 0) { 3272 // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range 3273 if ($min->equals($max)) { 3274 return false; 3275 } 3276 $x = $min->copy(); 3277 $x->_make_odd(); 3278 } 3279 3280 $initial_x = $x->copy(); 3281 3282 while (true) { 3283 if ($timeout !== false && time() - $start > $timeout) { 3284 return false; 3285 } 3286 3287 if ($x->isPrime()) { 3288 return $x; 3289 } 3290 3291 $x = $x->add($two); 3292 3293 if ($x->compare($max) > 0) { 3294 $x = $min->copy(); 3295 if ($x->equals($two)) { 3296 return $x; 3297 } 3298 $x->_make_odd(); 3299 } 3300 3301 if ($x->equals($initial_x)) { 3302 return false; 3303 } 3304 } 3305 } 3306 3307 /** 3308 * Make the current number odd 3309 * 3310 * If the current number is odd it'll be unchanged. If it's even, one will be added to it. 3311 * 3312 * @see self::randomPrime() 3313 * @access private 3314 */ 3315 function _make_odd() 3316 { 3317 switch (MATH_BIGINTEGER_MODE) { 3318 case self::MODE_GMP: 3319 gmp_setbit($this->value, 0); 3320 break; 3321 case self::MODE_BCMATH: 3322 if ($this->value[strlen($this->value) - 1] % 2 == 0) { 3323 $this->value = bcadd($this->value, '1'); 3324 } 3325 break; 3326 default: 3327 $this->value[0] |= 1; 3328 } 3329 } 3330 3331 /** 3332 * Checks a numer to see if it's prime 3333 * 3334 * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the 3335 * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads 3336 * on a website instead of just one. 3337 * 3338 * @param \phpseclib\Math\BigInteger $t 3339 * @return bool 3340 * @access public 3341 * @internal Uses the 3342 * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See 3343 * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}. 3344 */ 3345 function isPrime($t = false) 3346 { 3347 $length = strlen($this->toBytes()); 3348 3349 if (!$t) { 3350 // see HAC 4.49 "Note (controlling the error probability)" 3351 // @codingStandardsIgnoreStart 3352 if ($length >= 163) { $t = 2; } // floor(1300 / 8) 3353 else if ($length >= 106) { $t = 3; } // floor( 850 / 8) 3354 else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8) 3355 else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8) 3356 else if ($length >= 56 ) { $t = 6; } // floor( 450 / 8) 3357 else if ($length >= 50 ) { $t = 7; } // floor( 400 / 8) 3358 else if ($length >= 43 ) { $t = 8; } // floor( 350 / 8) 3359 else if ($length >= 37 ) { $t = 9; } // floor( 300 / 8) 3360 else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8) 3361 else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8) 3362 else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8) 3363 else { $t = 27; } 3364 // @codingStandardsIgnoreEnd 3365 } 3366 3367 // ie. gmp_testbit($this, 0) 3368 // ie. isEven() or !isOdd() 3369 switch (MATH_BIGINTEGER_MODE) { 3370 case self::MODE_GMP: 3371 return gmp_prob_prime($this->value, $t) != 0; 3372 case self::MODE_BCMATH: 3373 if ($this->value === '2') { 3374 return true; 3375 } 3376 if ($this->value[strlen($this->value) - 1] % 2 == 0) { 3377 return false; 3378 } 3379 break; 3380 default: 3381 if ($this->value == array(2)) { 3382 return true; 3383 } 3384 if (~$this->value[0] & 1) { 3385 return false; 3386 } 3387 } 3388 3389 static $primes, $zero, $one, $two; 3390 3391 if (!isset($primes)) { 3392 $primes = array( 3393 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 3394 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 3395 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 3396 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 3397 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 3398 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 3399 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 3400 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 3401 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 3402 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 3403 953, 967, 971, 977, 983, 991, 997 3404 ); 3405 3406 if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { 3407 for ($i = 0; $i < count($primes); ++$i) { 3408 $primes[$i] = new static($primes[$i]); 3409 } 3410 } 3411 3412 $zero = new static(); 3413 $one = new static(1); 3414 $two = new static(2); 3415 } 3416 3417 if ($this->equals($one)) { 3418 return false; 3419 } 3420 3421 // see HAC 4.4.1 "Random search for probable primes" 3422 if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { 3423 foreach ($primes as $prime) { 3424 list(, $r) = $this->divide($prime); 3425 if ($r->equals($zero)) { 3426 return $this->equals($prime); 3427 } 3428 } 3429 } else { 3430 $value = $this->value; 3431 foreach ($primes as $prime) { 3432 list(, $r) = $this->_divide_digit($value, $prime); 3433 if (!$r) { 3434 return count($value) == 1 && $value[0] == $prime; 3435 } 3436 } 3437 } 3438 3439 $n = $this->copy(); 3440 $n_1 = $n->subtract($one); 3441 $n_2 = $n->subtract($two); 3442 3443 $r = $n_1->copy(); 3444 $r_value = $r->value; 3445 // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); 3446 if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { 3447 $s = 0; 3448 // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier 3449 while ($r->value[strlen($r->value) - 1] % 2 == 0) { 3450 $r->value = bcdiv($r->value, '2', 0); 3451 ++$s; 3452 } 3453 } else { 3454 for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { 3455 $temp = ~$r_value[$i] & 0xFFFFFF; 3456 for ($j = 1; ($temp >> $j) & 1; ++$j) { 3457 } 3458 if ($j != 25) { 3459 break; 3460 } 3461 } 3462 $s = 26 * $i + $j; 3463 $r->_rshift($s); 3464 } 3465 3466 for ($i = 0; $i < $t; ++$i) { 3467 $a = $this->random($two, $n_2); 3468 $y = $a->modPow($r, $n); 3469 3470 if (!$y->equals($one) && !$y->equals($n_1)) { 3471 for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) { 3472 $y = $y->modPow($two, $n); 3473 if ($y->equals($one)) { 3474 return false; 3475 } 3476 } 3477 3478 if (!$y->equals($n_1)) { 3479 return false; 3480 } 3481 } 3482 } 3483 return true; 3484 } 3485 3486 /** 3487 * Logical Left Shift 3488 * 3489 * Shifts BigInteger's by $shift bits. 3490 * 3491 * @param int $shift 3492 * @access private 3493 */ 3494 function _lshift($shift) 3495 { 3496 if ($shift == 0) { 3497 return; 3498 } 3499 3500 $num_digits = (int) ($shift / self::$base); 3501 $shift %= self::$base; 3502 $shift = 1 << $shift; 3503 3504 $carry = 0; 3505 3506 for ($i = 0; $i < count($this->value); ++$i) { 3507 $temp = $this->value[$i] * $shift + $carry; 3508 $carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31); 3509 $this->value[$i] = (int) ($temp - $carry * self::$baseFull); 3510 } 3511 3512 if ($carry) { 3513 $this->value[count($this->value)] = $carry; 3514 } 3515 3516 while ($num_digits--) { 3517 array_unshift($this->value, 0); 3518 } 3519 } 3520 3521 /** 3522 * Logical Right Shift 3523 * 3524 * Shifts BigInteger's by $shift bits. 3525 * 3526 * @param int $shift 3527 * @access private 3528 */ 3529 function _rshift($shift) 3530 { 3531 if ($shift == 0) { 3532 return; 3533 } 3534 3535 $num_digits = (int) ($shift / self::$base); 3536 $shift %= self::$base; 3537 $carry_shift = self::$base - $shift; 3538 $carry_mask = (1 << $shift) - 1; 3539 3540 if ($num_digits) { 3541 $this->value = array_slice($this->value, $num_digits); 3542 } 3543 3544 $carry = 0; 3545 3546 for ($i = count($this->value) - 1; $i >= 0; --$i) { 3547 $temp = $this->value[$i] >> $shift | $carry; 3548 $carry = ($this->value[$i] & $carry_mask) << $carry_shift; 3549 $this->value[$i] = $temp; 3550 } 3551 3552 $this->value = $this->_trim($this->value); 3553 } 3554 3555 /** 3556 * Normalize 3557 * 3558 * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision 3559 * 3560 * @param \phpseclib\Math\BigInteger 3561 * @return \phpseclib\Math\BigInteger 3562 * @see self::_trim() 3563 * @access private 3564 */ 3565 function _normalize($result) 3566 { 3567 $result->precision = $this->precision; 3568 $result->bitmask = $this->bitmask; 3569 3570 switch (MATH_BIGINTEGER_MODE) { 3571 case self::MODE_GMP: 3572 if ($this->bitmask !== false) { 3573 $flip = gmp_cmp($result->value, gmp_init(0)) < 0; 3574 if ($flip) { 3575 $result->value = gmp_neg($result->value); 3576 } 3577 $result->value = gmp_and($result->value, $result->bitmask->value); 3578 if ($flip) { 3579 $result->value = gmp_neg($result->value); 3580 } 3581 } 3582 3583 return $result; 3584 case self::MODE_BCMATH: 3585 if (!empty($result->bitmask->value)) { 3586 $result->value = bcmod($result->value, $result->bitmask->value); 3587 } 3588 3589 return $result; 3590 } 3591 3592 $value = &$result->value; 3593 3594 if (!count($value)) { 3595 $result->is_negative = false; 3596 return $result; 3597 } 3598 3599 $value = $this->_trim($value); 3600 3601 if (!empty($result->bitmask->value)) { 3602 $length = min(count($value), count($this->bitmask->value)); 3603 $value = array_slice($value, 0, $length); 3604 3605 for ($i = 0; $i < $length; ++$i) { 3606 $value[$i] = $value[$i] & $this->bitmask->value[$i]; 3607 } 3608 } 3609 3610 return $result; 3611 } 3612 3613 /** 3614 * Trim 3615 * 3616 * Removes leading zeros 3617 * 3618 * @param array $value 3619 * @return \phpseclib\Math\BigInteger 3620 * @access private 3621 */ 3622 function _trim($value) 3623 { 3624 for ($i = count($value) - 1; $i >= 0; --$i) { 3625 if ($value[$i]) { 3626 break; 3627 } 3628 unset($value[$i]); 3629 } 3630 3631 return $value; 3632 } 3633 3634 /** 3635 * Array Repeat 3636 * 3637 * @param $input Array 3638 * @param $multiplier mixed 3639 * @return array 3640 * @access private 3641 */ 3642 function _array_repeat($input, $multiplier) 3643 { 3644 return ($multiplier) ? array_fill(0, $multiplier, $input) : array(); 3645 } 3646 3647 /** 3648 * Logical Left Shift 3649 * 3650 * Shifts binary strings $shift bits, essentially multiplying by 2**$shift. 3651 * 3652 * @param $x String 3653 * @param $shift Integer 3654 * @return string 3655 * @access private 3656 */ 3657 function _base256_lshift(&$x, $shift) 3658 { 3659 if ($shift == 0) { 3660 return; 3661 } 3662 3663 $num_bytes = $shift >> 3; // eg. floor($shift/8) 3664 $shift &= 7; // eg. $shift % 8 3665 3666 $carry = 0; 3667 for ($i = strlen($x) - 1; $i >= 0; --$i) { 3668 $temp = ord($x[$i]) << $shift | $carry; 3669 $x[$i] = chr($temp); 3670 $carry = $temp >> 8; 3671 } 3672 $carry = ($carry != 0) ? chr($carry) : ''; 3673 $x = $carry . $x . str_repeat(chr(0), $num_bytes); 3674 } 3675 3676 /** 3677 * Logical Right Shift 3678 * 3679 * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder. 3680 * 3681 * @param $x String 3682 * @param $shift Integer 3683 * @return string 3684 * @access private 3685 */ 3686 function _base256_rshift(&$x, $shift) 3687 { 3688 if ($shift == 0) { 3689 $x = ltrim($x, chr(0)); 3690 return ''; 3691 } 3692 3693 $num_bytes = $shift >> 3; // eg. floor($shift/8) 3694 $shift &= 7; // eg. $shift % 8 3695 3696 $remainder = ''; 3697 if ($num_bytes) { 3698 $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes; 3699 $remainder = substr($x, $start); 3700 $x = substr($x, 0, -$num_bytes); 3701 } 3702 3703 $carry = 0; 3704 $carry_shift = 8 - $shift; 3705 for ($i = 0; $i < strlen($x); ++$i) { 3706 $temp = (ord($x[$i]) >> $shift) | $carry; 3707 $carry = (ord($x[$i]) << $carry_shift) & 0xFF; 3708 $x[$i] = chr($temp); 3709 } 3710 $x = ltrim($x, chr(0)); 3711 3712 $remainder = chr($carry >> $carry_shift) . $remainder; 3713 3714 return ltrim($remainder, chr(0)); 3715 } 3716 3717 // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long 3718 // at 32-bits, while java's longs are 64-bits. 3719 3720 /** 3721 * Converts 32-bit integers to bytes. 3722 * 3723 * @param int $x 3724 * @return string 3725 * @access private 3726 */ 3727 function _int2bytes($x) 3728 { 3729 return ltrim(pack('N', $x), chr(0)); 3730 } 3731 3732 /** 3733 * Converts bytes to 32-bit integers 3734 * 3735 * @param string $x 3736 * @return int 3737 * @access private 3738 */ 3739 function _bytes2int($x) 3740 { 3741 $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT)); 3742 return $temp['int']; 3743 } 3744 3745 /** 3746 * DER-encode an integer 3747 * 3748 * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL 3749 * 3750 * @see self::modPow() 3751 * @access private 3752 * @param int $length 3753 * @return string 3754 */ 3755 function _encodeASN1Length($length) 3756 { 3757 if ($length <= 0x7F) { 3758 return chr($length); 3759 } 3760 3761 $temp = ltrim(pack('N', $length), chr(0)); 3762 return pack('Ca*', 0x80 | strlen($temp), $temp); 3763 } 3764 3765 /** 3766 * Single digit division 3767 * 3768 * Even if int64 is being used the division operator will return a float64 value 3769 * if the dividend is not evenly divisible by the divisor. Since a float64 doesn't 3770 * have the precision of int64 this is a problem so, when int64 is being used, 3771 * we'll guarantee that the dividend is divisible by first subtracting the remainder. 3772 * 3773 * @access private 3774 * @param int $x 3775 * @param int $y 3776 * @return int 3777 */ 3778 function _safe_divide($x, $y) 3779 { 3780 if (self::$base === 26) { 3781 return (int) ($x / $y); 3782 } 3783 3784 // self::$base === 31 3785 return ($x - ($x % $y)) / $y; 3786 } 3787 }
Download modules/phpseclib/Math/BigInteger.class.php
History Sat, 31 Oct 2020 00:43:29 +0100 Jan Dankert New: Support for OpenId Connect; Removed: Support for LDAP.