> and << cannot be used, nor can the modulo operator %, * which only supports integers. Although this fact will slow this library down, the fact that such a high * base is being used should more than compensate. * * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie. * (new \phpseclib\Math\BigInteger(pow(2, 26)))->value = array(0, 1) * * Useful resources are as follows: * * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)} * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)} * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip * * Here's an example of how to use this library: * * add($b); * * echo $c->toString(); // outputs 5 * ?> * * * @category Math * @package BigInteger * @author Jim Wigginton * @copyright 2006 Jim Wigginton * @license http://www.opensource.org/licenses/mit-license.html MIT License */ namespace phpseclib\Math; use phpseclib3\Math\BigInteger as BigInteger2; /** * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 * numbers. * * @package BigInteger * @method string toString() * @method string toBytes() * @method string toHex() * @method string toBits() * @method BigInteger add(BigInteger $y) * @method BigInteger subtract(BigInteger $y) * @method BigInteger multiply(BigInteger $x) * @method array{BigInteger, BigInteger} divide(BigInteger $x) * @method BigInteger modInverse(BigInteger $n) * @method {'gcd': BigInteger, 'x': BigInteger, 'y': BigInteger} extendedGCD(BigInteger $n) * @method BigInteger gcd(BigInteger $n) * @method BigInteger abs() * @method void setPrecision(int $bits) * @method int|bool getPrecision() * @method BigInteger powMod(BigInteger $e, BigInteger $n) * @method BigInteger modPow(BigInteger $e, BigInteger $n) * @method int compare(BigInteger $y) * @method bool equals(BigInteger $x) * @method BigInteger bitwise_not() * @method BigInteger bitwise_and(BigInteger $x) * @method BigInteger bitwise_or(BigInteger $x) * @method BigInteger bitwise_rightShift($shift) * @method BigInteger bitwise_leftShift($shift) * @method BigInteger bitwise_leftRotate($shift) * @method BigInteger bitwise_rightRotate($shift) * @method {'min': BigInteger, 'max': BigInteger} minMaxBits($bits) * @method int getLength() * @method int getLengthInBytes() * @method bool isPrime(int|bool $t = false) * @method BigInteger root(int $n = 2) * @method BigInteger pow(BigInteger $n) * @method static BigInteger min(BigInteger ...$nums) * @method static BigInteger max(BigInteger ...$nums) * @method bool between(BigInteger $min, BigInteger $max) * @method bool isOdd() * @method bool testBit(int $x) * @method bool isNegative() * @method BigInteger negate() * @method callable createRecurringModuloFunction() * @method BigInteger[] bitwise_split(int $split) * @author Jim Wigginton * @access public */ class BigInteger { /**#@+ * Array constants * * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them. * * @access private */ /** * $result[self::VALUE] contains the value. */ const VALUE = 0; /** * $result[self::SIGN] contains the sign. */ const SIGN = 1; /**#@-*/ /**#@+ * @access private * @see BigInteger::_montgomery() * @see BigInteger::_barrett() */ /** * Cache constants * * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. */ const VARIABLE = 0; /** * $cache[self::DATA] contains the cached data. */ const DATA = 1; /**#@-*/ /**#@+ * Mode constants. * * @access private * @see BigInteger::__construct() */ /** * To use the pure-PHP implementation */ const MODE_INTERNAL = 1; /** * To use the BCMath library * * (if enabled; otherwise, the internal implementation will be used) */ const MODE_BCMATH = 2; /** * To use the GMP library * * (if present; otherwise, either the BCMath or the internal implementation will be used) */ const MODE_GMP = 3; /**#@-*/ /** * The BigInteger object * * @var \phpseclib3\Math\BigInteger * @access private */ private $bigint; /** * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers. * * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. * * Here's an example: * * toString(); // outputs 50 * ?> * * * @param $x base-10 number or base-$base number if $base set. * @param int $base * @return \phpseclib\Math\BigInteger * @access public */ public function __construct($x = 0, $base = 10) { $this->bigint = new BigInteger2($x, $base); } /** * __call() magic method * * @access public */ public function __call($name, $args) { foreach ($args as &$arg) { if ($arg instanceof BigInteger) { $arg = $arg->bigint; } } $result = $this->bigint->$name(...$args); if (!$result instanceof BigInteger2) { return $result; } $temp = new static; $temp->bigint = $result; return $temp; } /** * __toString() magic method * * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call * toString(). * * @access public * @internal Implemented per a suggestion by Techie-Michael - thanks! */ public function __toString() { return $this->bigint->__toString(); } /** * __debugInfo() magic method * * Will be called, automatically, when print_r() or var_dump() are called * * @access public */ public function __debugInfo() { return $this->bigint->__debugInfo(); } /** * Generate a random number * * Returns a random number between $min and $max where $min and $max * can be defined using one of the two methods: * * $min->random($max) * $max->random($min) * * @param \phpseclib\Math\BigInteger $arg1 * @param \phpseclib\Math\BigInteger $arg2 * @return \phpseclib\Math\BigInteger * @access public * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a BigInteger object. * That method is still supported for BC purposes. */ public function random($arg1, $arg2 = false) { $temp = new static; $temp->bigint = BigInteger2::randomRange( $arg1->bigint, $arg2 instanceof BigInteger ? $arg2->bigint : $this->bigint ); return $temp; } /** * Generate a random prime number. * * If there's not a prime within the given range, false will be returned. * If more than $timeout seconds have elapsed, give up and return false. * * @param \phpseclib\Math\BigInteger $arg1 * @param \phpseclib\Math\BigInteger $arg2 * @return Math_BigInteger|false * @access public * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}. */ public function randomPrime($arg1, $arg2 = false) { $temp = new static; $temp->bigint = BigInteger2::randomRange( $arg1->bigint, $arg2 instanceof BigInteger ? $arg2->bigint : $this->bigint ); return $temp; } /** * Logical Exclusive-Or * * See https://github.com/phpseclib/phpseclib/issues/1245 for more context * * @param \phpseclib\Math\BigInteger $x * @access public * @return \phpseclib\Math\BigInteger */ public function bitwise_xor($x) { $temp = new static; $temp->bigint = $this->bigint->abs()->bitwise_xor($x->bigint->abs()); return $temp; } }