PageRenderTime 8ms CodeModel.GetById 3ms app.highlight 60ms RepoModel.GetById 1ms app.codeStats 1ms

/vendor/phpseclib/Math/BigInteger.php

https://github.com/KenjiOhtsuka/core
PHP | 3714 lines | 1983 code | 491 blank | 1240 comment | 401 complexity | aafc7122eb095e2112211e2b1392fc2e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   3
   4namespace PHPSecLib\Math;
   5
   6/**
   7 * Pure-PHP arbitrary precision integer arithmetic library.
   8 *
   9 * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,
  10 * and an internal implementation, otherwise.
  11 *
  12 * PHP versions 4 and 5
  13 *
  14 * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
  15 * {@link MATH_BIGINTEGER_MODE_INTERNAL MATH_BIGINTEGER_MODE_INTERNAL} mode)
  16 *
  17 * BigInteger uses base-2**26 to perform operations such as multiplication and division and
  18 * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction.  Because the largest possible
  19 * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
  20 * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
  21 * used.  As a consequence, bitwise operators such as >> and << cannot be used, nor can the modulo operator %,
  22 * which only supports integers.  Although this fact will slow this library down, the fact that such a high
  23 * base is being used should more than compensate.
  24 *
  25 * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format.  ie.
  26 * (new \PHPSecLib\Math\BigInteger(pow(2, 26)))->value = array(0, 1)
  27 *
  28 * Useful resources are as follows:
  29 *
  30 *  - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}
  31 *  - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}
  32 *  - Java's BigInteger classes.  See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip
  33 *
  34 * Here's an example of how to use this library:
  35 * <code>
  36 * <?php
  37 *    $a = new \PHPSecLib\Math\BigInteger(2);
  38 *    $b = new \PHPSecLib\Math\BigInteger(3);
  39 *
  40 *    $c = $a->add($b);
  41 *
  42 *    echo $c->toString(); // outputs 5
  43 * ?>
  44 * </code>
  45 *
  46 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  47 * of this software and associated documentation files (the "Software"), to deal
  48 * in the Software without restriction, including without limitation the rights
  49 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  50 * copies of the Software, and to permit persons to whom the Software is
  51 * furnished to do so, subject to the following conditions:
  52 *
  53 * The above copyright notice and this permission notice shall be included in
  54 * all copies or substantial portions of the Software.
  55 *
  56 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  57 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  58 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  59 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  60 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  61 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  62 * THE SOFTWARE.
  63 *
  64 * @category  Math
  65 * @package   Math_BigInteger
  66 * @author    Jim Wigginton <terrafrost@php.net>
  67 * @copyright MMVI Jim Wigginton
  68 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  69 * @link      http://pear.php.net/package/Math_BigInteger
  70 */
  71
  72use \phpseclib\Crypt\Random;
  73
  74/**#@+
  75 * Reduction constants
  76 *
  77 * @access private
  78 * @see BigInteger::_reduce()
  79 */
  80/**
  81 * @see BigInteger::_montgomery()
  82 * @see BigInteger::_prepMontgomery()
  83 */
  84define('MATH_BIGINTEGER_MONTGOMERY', 0);
  85/**
  86 * @see BigInteger::_barrett()
  87 */
  88define('MATH_BIGINTEGER_BARRETT', 1);
  89/**
  90 * @see BigInteger::_mod2()
  91 */
  92define('MATH_BIGINTEGER_POWEROF2', 2);
  93/**
  94 * @see BigInteger::_remainder()
  95 */
  96define('MATH_BIGINTEGER_CLASSIC', 3);
  97/**
  98 * @see BigInteger::__clone()
  99 */
 100define('MATH_BIGINTEGER_NONE', 4);
 101/**#@-*/
 102
 103/**#@+
 104 * Array constants
 105 *
 106 * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
 107 * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
 108 *
 109 * @access private
 110 */
 111/**
 112 * $result[MATH_BIGINTEGER_VALUE] contains the value.
 113 */
 114define('MATH_BIGINTEGER_VALUE', 0);
 115/**
 116 * $result[MATH_BIGINTEGER_SIGN] contains the sign.
 117 */
 118define('MATH_BIGINTEGER_SIGN', 1);
 119/**#@-*/
 120
 121/**#@+
 122 * @access private
 123 * @see BigInteger::_montgomery()
 124 * @see BigInteger::_barrett()
 125 */
 126/**
 127 * Cache constants
 128 *
 129 * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.
 130 */
 131define('MATH_BIGINTEGER_VARIABLE', 0);
 132/**
 133 * $cache[MATH_BIGINTEGER_DATA] contains the cached data.
 134 */
 135define('MATH_BIGINTEGER_DATA', 1);
 136/**#@-*/
 137
 138/**#@+
 139 * Mode constants.
 140 *
 141 * @access private
 142 * @see BigInteger::__construct()
 143 */
 144/**
 145 * To use the pure-PHP implementation
 146 */
 147define('MATH_BIGINTEGER_MODE_INTERNAL', 1);
 148/**
 149 * To use the BCMath library
 150 *
 151 * (if enabled; otherwise, the internal implementation will be used)
 152 */
 153define('MATH_BIGINTEGER_MODE_BCMATH', 2);
 154/**
 155 * To use the GMP library
 156 *
 157 * (if present; otherwise, either the BCMath or the internal implementation will be used)
 158 */
 159define('MATH_BIGINTEGER_MODE_GMP', 3);
 160/**#@-*/
 161
 162/**
 163 * Karatsuba Cutoff
 164 *
 165 * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
 166 *
 167 * @access private
 168 */
 169define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25);
 170
 171/**
 172 * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
 173 * numbers.
 174 *
 175 * @package Math_BigInteger
 176 * @author  Jim Wigginton <terrafrost@php.net>
 177 * @access  public
 178 */
 179class BigInteger
 180{
 181    /**
 182     * Holds the BigInteger's value.
 183     *
 184     * @var Array
 185     * @access private
 186     */
 187    var $value;
 188
 189    /**
 190     * Holds the BigInteger's magnitude.
 191     *
 192     * @var Boolean
 193     * @access private
 194     */
 195    var $is_negative = false;
 196
 197    /**
 198     * Random number generator function
 199     *
 200     * @access private
 201     */
 202    var $generator = 'mt_rand';
 203
 204    /**
 205     * Precision
 206     *
 207     * @see setPrecision()
 208     * @access private
 209     */
 210    var $precision = -1;
 211
 212    /**
 213     * Precision Bitmask
 214     *
 215     * @see setPrecision()
 216     * @access private
 217     */
 218    var $bitmask = false;
 219
 220    /**
 221     * Mode independent value used for serialization.
 222     *
 223     * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
 224     * a variable that'll be serializable regardless of whether or not extensions are being used.  Unlike $this->value,
 225     * however, $this->hex is only calculated when $this->__sleep() is called.
 226     *
 227     * @see __sleep()
 228     * @see __wakeup()
 229     * @var String
 230     * @access private
 231     */
 232    var $hex;
 233
 234    /**
 235     * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
 236     *
 237     * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
 238     * two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
 239     *
 240     * Here's an example:
 241     * <code>
 242     * <?php
 243     *    $a = new \PHPSecLib\Math\BigInteger('0x32', 16); // 50 in base-16
 244     *
 245     *    echo $a->toString(); // outputs 50
 246     * ?>
 247     * </code>
 248     *
 249     * @param optional $x base-10 number or base-$base number if $base set.
 250     * @param optional integer $base
 251     * @return \PHPSecLib\Math\BigInteger
 252     * @access public
 253     */
 254    function __construct($x = 0, $base = 10)
 255    {
 256        if ( !defined('MATH_BIGINTEGER_MODE') ) {
 257            switch (true) {
 258                case extension_loaded('gmp'):
 259                    define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
 260                    break;
 261                case extension_loaded('bcmath'):
 262                    define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);
 263                    break;
 264                default:
 265                    define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);
 266            }
 267        }
 268
 269        if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
 270            // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
 271            ob_start();
 272            @phpinfo();
 273            $content = ob_get_contents();
 274            ob_end_clean();
 275
 276            preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
 277
 278            $versions = array();
 279            if (!empty($matches[1])) {
 280                for ($i = 0; $i < count($matches[1]); $i++) {
 281                    $versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
 282                }
 283            }
 284
 285            // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
 286            switch (true) {
 287                case !isset($versions['Header']):
 288                case !isset($versions['Library']):
 289                case $versions['Header'] == $versions['Library']:
 290                    define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
 291                    break;
 292                default:
 293                    define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
 294            }
 295        }
 296
 297        if (!defined('PHP_INT_SIZE')) {
 298            define('PHP_INT_SIZE', 4);
 299        }
 300
 301        if (!defined('MATH_BIGINTEGER_BASE') && MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL) {
 302            switch (PHP_INT_SIZE) {
 303                case 8: // use 64-bit integers if int size is 8 bytes
 304                    define('MATH_BIGINTEGER_BASE',       31);
 305                    define('MATH_BIGINTEGER_BASE_FULL',  0x80000000);
 306                    define('MATH_BIGINTEGER_MAX_DIGIT',  0x7FFFFFFF);
 307                    define('MATH_BIGINTEGER_MSB',        0x40000000);
 308                    // 10**9 is the closest we can get to 2**31 without passing it
 309                    define('MATH_BIGINTEGER_MAX10',      1000000000);
 310                    define('MATH_BIGINTEGER_MAX10_LEN',  9);
 311                    // the largest digit that may be used in addition / subtraction
 312                    define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 62));
 313                    break;
 314                //case 4: // use 64-bit floats if int size is 4 bytes
 315                default:
 316                    define('MATH_BIGINTEGER_BASE',       26);
 317                    define('MATH_BIGINTEGER_BASE_FULL',  0x4000000);
 318                    define('MATH_BIGINTEGER_MAX_DIGIT',  0x3FFFFFF);
 319                    define('MATH_BIGINTEGER_MSB',        0x2000000);
 320                    // 10**7 is the closest to 2**26 without passing it
 321                    define('MATH_BIGINTEGER_MAX10',      10000000);
 322                    define('MATH_BIGINTEGER_MAX10_LEN',  7);
 323                    // the largest digit that may be used in addition / subtraction
 324                    // we do pow(2, 52) instead of using 4503599627370496 directly because some
 325                    // PHP installations will truncate 4503599627370496.
 326                    define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 52));
 327            }
 328        }
 329
 330        switch ( MATH_BIGINTEGER_MODE ) {
 331            case MATH_BIGINTEGER_MODE_GMP:
 332                switch (true) {
 333                    case is_resource($x) && get_resource_type($x) == 'GMP integer':
 334                    // PHP 5.6 switched GMP from using resources to objects
 335                    case is_object($x) && get_class($x) == 'GMP':
 336                        $this->value = $x;
 337                        return;
 338                }
 339                $this->value = gmp_init(0);
 340                break;
 341            case MATH_BIGINTEGER_MODE_BCMATH:
 342                $this->value = '0';
 343                break;
 344            default:
 345                $this->value = array();
 346        }
 347
 348        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
 349        // '0' is the only value like this per http://php.net/empty
 350        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
 351            return;
 352        }
 353
 354        switch ($base) {
 355            case -256:
 356                if (ord($x[0]) & 0x80) {
 357                    $x = ~$x;
 358                    $this->is_negative = true;
 359                }
 360            case  256:
 361                switch ( MATH_BIGINTEGER_MODE ) {
 362                    case MATH_BIGINTEGER_MODE_GMP:
 363                        $sign = $this->is_negative ? '-' : '';
 364                        $this->value = gmp_init($sign . '0x' . bin2hex($x));
 365                        break;
 366                    case MATH_BIGINTEGER_MODE_BCMATH:
 367                        // round $len to the nearest 4 (thanks, DavidMJ!)
 368                        $len = (strlen($x) + 3) & 0xFFFFFFFC;
 369
 370                        $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
 371
 372                        for ($i = 0; $i < $len; $i+= 4) {
 373                            $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32
 374                            $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0);
 375                        }
 376
 377                        if ($this->is_negative) {
 378                            $this->value = '-' . $this->value;
 379                        }
 380
 381                        break;
 382                    // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
 383                    default:
 384                        while (strlen($x)) {
 385                            $this->value[] = $this->_bytes2int($this->_base256_rshift($x, MATH_BIGINTEGER_BASE));
 386                        }
 387                }
 388
 389                if ($this->is_negative) {
 390                    if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
 391                        $this->is_negative = false;
 392                    }
 393                    $temp = $this->add(new static('-1'));
 394                    $this->value = $temp->value;
 395                }
 396                break;
 397            case  16:
 398            case -16:
 399                if ($base > 0 && $x[0] == '-') {
 400                    $this->is_negative = true;
 401                    $x = substr($x, 1);
 402                }
 403
 404                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
 405
 406                $is_negative = false;
 407                if ($base < 0 && hexdec($x[0]) >= 8) {
 408                    $this->is_negative = $is_negative = true;
 409                    $x = bin2hex(~pack('H*', $x));
 410                }
 411
 412                switch ( MATH_BIGINTEGER_MODE ) {
 413                    case MATH_BIGINTEGER_MODE_GMP:
 414                        $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
 415                        $this->value = gmp_init($temp);
 416                        $this->is_negative = false;
 417                        break;
 418                    case MATH_BIGINTEGER_MODE_BCMATH:
 419                        $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
 420                        $temp = new static(pack('H*', $x), 256);
 421                        $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
 422                        $this->is_negative = false;
 423                        break;
 424                    default:
 425                        $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
 426                        $temp = new static(pack('H*', $x), 256);
 427                        $this->value = $temp->value;
 428                }
 429
 430                if ($is_negative) {
 431                    $temp = $this->add(new static('-1'));
 432                    $this->value = $temp->value;
 433                }
 434                break;
 435            case  10:
 436            case -10:
 437                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
 438                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
 439                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
 440                $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
 441
 442                switch ( MATH_BIGINTEGER_MODE ) {
 443                    case MATH_BIGINTEGER_MODE_GMP:
 444                        $this->value = gmp_init($x);
 445                        break;
 446                    case MATH_BIGINTEGER_MODE_BCMATH:
 447                        // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
 448                        // results then doing it on '-1' does (modInverse does $x[0])
 449                        $this->value = $x === '-' ? '0' : (string) $x;
 450                        break;
 451                    default:
 452                        $temp = new static();
 453
 454                        $multiplier = new static();
 455                        $multiplier->value = array(MATH_BIGINTEGER_MAX10);
 456
 457                        if ($x[0] == '-') {
 458                            $this->is_negative = true;
 459                            $x = substr($x, 1);
 460                        }
 461
 462                        $x = str_pad($x, strlen($x) + ((MATH_BIGINTEGER_MAX10_LEN - 1) * strlen($x)) % MATH_BIGINTEGER_MAX10_LEN, 0, STR_PAD_LEFT);
 463                        while (strlen($x)) {
 464                            $temp = $temp->multiply($multiplier);
 465                            $temp = $temp->add(new static($this->_int2bytes(substr($x, 0, MATH_BIGINTEGER_MAX10_LEN)), 256));
 466                            $x = substr($x, MATH_BIGINTEGER_MAX10_LEN);
 467                        }
 468
 469                        $this->value = $temp->value;
 470                }
 471                break;
 472            case  2: // base-2 support originally implemented by Lluis Pamies - thanks!
 473            case -2:
 474                if ($base > 0 && $x[0] == '-') {
 475                    $this->is_negative = true;
 476                    $x = substr($x, 1);
 477                }
 478
 479                $x = preg_replace('#^([01]*).*#', '$1', $x);
 480                $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
 481
 482                $str = '0x';
 483                while (strlen($x)) {
 484                    $part = substr($x, 0, 4);
 485                    $str.= dechex(bindec($part));
 486                    $x = substr($x, 4);
 487                }
 488
 489                if ($this->is_negative) {
 490                    $str = '-' . $str;
 491                }
 492
 493                $temp = new static($str, 8 * $base); // ie. either -16 or +16
 494                $this->value = $temp->value;
 495                $this->is_negative = $temp->is_negative;
 496
 497                break;
 498            default:
 499                // base not supported, so we'll let $this == 0
 500        }
 501    }
 502
 503    /**
 504     * Converts a BigInteger to a byte string (eg. base-256).
 505     *
 506     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
 507     * saved as two's compliment.
 508     *
 509     * Here's an example:
 510     * <code>
 511     * <?php
 512     *    $a = new \PHPSecLib\Math\BigInteger('65');
 513     *
 514     *    echo $a->toBytes(); // outputs chr(65)
 515     * ?>
 516     * </code>
 517     *
 518     * @param Boolean $twos_compliment
 519     * @return String
 520     * @access public
 521     * @internal Converts a base-2**26 number to base-2**8
 522     */
 523    function toBytes($twos_compliment = false)
 524    {
 525        if ($twos_compliment) {
 526            $comparison = $this->compare(new static());
 527            if ($comparison == 0) {
 528                return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 529            }
 530
 531            $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy();
 532            $bytes = $temp->toBytes();
 533
 534            if (empty($bytes)) { // eg. if the number we're trying to convert is -1
 535                $bytes = chr(0);
 536            }
 537
 538            if (ord($bytes[0]) & 0x80) {
 539                $bytes = chr(0) . $bytes;
 540            }
 541
 542            return $comparison < 0 ? ~$bytes : $bytes;
 543        }
 544
 545        switch ( MATH_BIGINTEGER_MODE ) {
 546            case MATH_BIGINTEGER_MODE_GMP:
 547                if (gmp_cmp($this->value, gmp_init(0)) == 0) {
 548                    return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 549                }
 550
 551                $temp = gmp_strval(gmp_abs($this->value), 16);
 552                $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
 553                $temp = pack('H*', $temp);
 554
 555                return $this->precision > 0 ?
 556                    substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
 557                    ltrim($temp, chr(0));
 558            case MATH_BIGINTEGER_MODE_BCMATH:
 559                if ($this->value === '0') {
 560                    return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 561                }
 562
 563                $value = '';
 564                $current = $this->value;
 565
 566                if ($current[0] == '-') {
 567                    $current = substr($current, 1);
 568                }
 569
 570                while (bccomp($current, '0', 0) > 0) {
 571                    $temp = bcmod($current, '16777216');
 572                    $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
 573                    $current = bcdiv($current, '16777216', 0);
 574                }
 575
 576                return $this->precision > 0 ?
 577                    substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
 578                    ltrim($value, chr(0));
 579        }
 580
 581        if (!count($this->value)) {
 582            return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
 583        }
 584        $result = $this->_int2bytes($this->value[count($this->value) - 1]);
 585
 586        $temp = $this->copy();
 587
 588        for ($i = count($temp->value) - 2; $i >= 0; --$i) {
 589            $temp->_base256_lshift($result, MATH_BIGINTEGER_BASE);
 590            $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
 591        }
 592
 593        return $this->precision > 0 ?
 594            str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) :
 595            $result;
 596    }
 597
 598    /**
 599     * Converts a BigInteger to a hex string (eg. base-16)).
 600     *
 601     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
 602     * saved as two's compliment.
 603     *
 604     * Here's an example:
 605     * <code>
 606     * <?php
 607     *    $a = new \PHPSecLib\Math\BigInteger('65');
 608     *
 609     *    echo $a->toHex(); // outputs '41'
 610     * ?>
 611     * </code>
 612     *
 613     * @param Boolean $twos_compliment
 614     * @return String
 615     * @access public
 616     * @internal Converts a base-2**26 number to base-2**8
 617     */
 618    function toHex($twos_compliment = false)
 619    {
 620        return bin2hex($this->toBytes($twos_compliment));
 621    }
 622
 623    /**
 624     * Converts a BigInteger to a bit string (eg. base-2).
 625     *
 626     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
 627     * saved as two's compliment.
 628     *
 629     * Here's an example:
 630     * <code>
 631     * <?php
 632     *    $a = new \PHPSecLib\Math\BigInteger('65');
 633     *
 634     *    echo $a->toBits(); // outputs '1000001'
 635     * ?>
 636     * </code>
 637     *
 638     * @param Boolean $twos_compliment
 639     * @return String
 640     * @access public
 641     * @internal Converts a base-2**26 number to base-2**2
 642     */
 643    function toBits($twos_compliment = false)
 644    {
 645        $hex = $this->toHex($twos_compliment);
 646        $bits = '';
 647        for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
 648            $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
 649        }
 650        if ($start) { // hexdec('') == 0
 651            $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
 652        }
 653        $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
 654
 655        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
 656            return '0' . $result;
 657        }
 658
 659        return $result;
 660    }
 661
 662    /**
 663     * Converts a BigInteger to a base-10 number.
 664     *
 665     * Here's an example:
 666     * <code>
 667     * <?php
 668     *    $a = new \PHPSecLib\Math\BigInteger('50');
 669     *
 670     *    echo $a->toString(); // outputs 50
 671     * ?>
 672     * </code>
 673     *
 674     * @return String
 675     * @access public
 676     * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
 677     */
 678    function toString()
 679    {
 680        switch ( MATH_BIGINTEGER_MODE ) {
 681            case MATH_BIGINTEGER_MODE_GMP:
 682                return gmp_strval($this->value);
 683            case MATH_BIGINTEGER_MODE_BCMATH:
 684                if ($this->value === '0') {
 685                    return '0';
 686                }
 687
 688                return ltrim($this->value, '0');
 689        }
 690
 691        if (!count($this->value)) {
 692            return '0';
 693        }
 694
 695        $temp = $this->copy();
 696        $temp->is_negative = false;
 697
 698        $divisor = new static();
 699        $divisor->value = array(MATH_BIGINTEGER_MAX10);
 700        $result = '';
 701        while (count($temp->value)) {
 702            list($temp, $mod) = $temp->divide($divisor);
 703            $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', MATH_BIGINTEGER_MAX10_LEN, '0', STR_PAD_LEFT) . $result;
 704        }
 705        $result = ltrim($result, '0');
 706        if (empty($result)) {
 707            $result = '0';
 708        }
 709
 710        if ($this->is_negative) {
 711            $result = '-' . $result;
 712        }
 713
 714        return $result;
 715    }
 716
 717    /**
 718     * Copy an object
 719     *
 720     * PHP5 passes objects by reference while PHP4 passes by value.  As such, we need a function to guarantee
 721     * that all objects are passed by value, when appropriate.  More information can be found here:
 722     *
 723     * {@link http://php.net/language.oop5.basic#51624}
 724     *
 725     * @access public
 726     * @see __clone()
 727     * @return \PHPSecLib\Math\BigInteger
 728     */
 729    function copy()
 730    {
 731        $temp = new static();
 732        $temp->value = $this->value;
 733        $temp->is_negative = $this->is_negative;
 734        $temp->generator = $this->generator;
 735        $temp->precision = $this->precision;
 736        $temp->bitmask = $this->bitmask;
 737        return $temp;
 738    }
 739
 740    /**
 741     *  __toString() magic method
 742     *
 743     * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call
 744     * toString().
 745     *
 746     * @access public
 747     * @internal Implemented per a suggestion by Techie-Michael - thanks!
 748     */
 749    function __toString()
 750    {
 751        return $this->toString();
 752    }
 753
 754    /**
 755     * __clone() magic method
 756     *
 757     * Although you can call BigInteger::__toString() directly in PHP5, you cannot call BigInteger::__clone() directly
 758     * 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
 759     * only syntax of $y = clone $x.  As such, if you're trying to write an application that works on both PHP4 and
 760     * PHP5, call BigInteger::copy(), instead.
 761     *
 762     * @access public
 763     * @see copy()
 764     * @return \PHPSecLib\Math\BigInteger
 765     */
 766    function __clone()
 767    {
 768        return $this->copy();
 769    }
 770
 771    /**
 772     *  __sleep() magic method
 773     *
 774     * Will be called, automatically, when serialize() is called on a BigInteger object.
 775     *
 776     * @see __wakeup()
 777     * @access public
 778     */
 779    function __sleep()
 780    {
 781        $this->hex = $this->toHex(true);
 782        $vars = array('hex');
 783        if ($this->generator != 'mt_rand') {
 784            $vars[] = 'generator';
 785        }
 786        if ($this->precision > 0) {
 787            $vars[] = 'precision';
 788        }
 789        return $vars;
 790
 791    }
 792
 793    /**
 794     *  __wakeup() magic method
 795     *
 796     * Will be called, automatically, when unserialize() is called on a BigInteger object.
 797     *
 798     * @see __sleep()
 799     * @access public
 800     */
 801    function __wakeup()
 802    {
 803        $temp = new static($this->hex, -16);
 804        $this->value = $temp->value;
 805        $this->is_negative = $temp->is_negative;
 806        if ($this->precision > 0) {
 807            // recalculate $this->bitmask
 808            $this->setPrecision($this->precision);
 809        }
 810    }
 811
 812    /**
 813     * Adds two BigIntegers.
 814     *
 815     * Here's an example:
 816     * <code>
 817     * <?php
 818     *    $a = new \PHPSecLib\Math\BigInteger('10');
 819     *    $b = new \PHPSecLib\Math\BigInteger('20');
 820     *
 821     *    $c = $a->add($b);
 822     *
 823     *    echo $c->toString(); // outputs 30
 824     * ?>
 825     * </code>
 826     *
 827     * @param \PHPSecLib\Math\BigInteger $y
 828     * @return \PHPSecLib\Math\BigInteger
 829     * @access public
 830     * @internal Performs base-2**52 addition
 831     */
 832    function add($y)
 833    {
 834        switch ( MATH_BIGINTEGER_MODE ) {
 835            case MATH_BIGINTEGER_MODE_GMP:
 836                $temp = new static();
 837                $temp->value = gmp_add($this->value, $y->value);
 838
 839                return $this->_normalize($temp);
 840            case MATH_BIGINTEGER_MODE_BCMATH:
 841                $temp = new static();
 842                $temp->value = bcadd($this->value, $y->value, 0);
 843
 844                return $this->_normalize($temp);
 845        }
 846
 847        $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative);
 848
 849        $result = new static();
 850        $result->value = $temp[MATH_BIGINTEGER_VALUE];
 851        $result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
 852
 853        return $this->_normalize($result);
 854    }
 855
 856    /**
 857     * Performs addition.
 858     *
 859     * @param Array $x_value
 860     * @param Boolean $x_negative
 861     * @param Array $y_value
 862     * @param Boolean $y_negative
 863     * @return Array
 864     * @access private
 865     */
 866    function _add($x_value, $x_negative, $y_value, $y_negative)
 867    {
 868        $x_size = count($x_value);
 869        $y_size = count($y_value);
 870
 871        if ($x_size == 0) {
 872            return array(
 873                MATH_BIGINTEGER_VALUE => $y_value,
 874                MATH_BIGINTEGER_SIGN => $y_negative
 875            );
 876        } else if ($y_size == 0) {
 877            return array(
 878                MATH_BIGINTEGER_VALUE => $x_value,
 879                MATH_BIGINTEGER_SIGN => $x_negative
 880            );
 881        }
 882
 883        // subtract, if appropriate
 884        if ( $x_negative != $y_negative ) {
 885            if ( $x_value == $y_value ) {
 886                return array(
 887                    MATH_BIGINTEGER_VALUE => array(),
 888                    MATH_BIGINTEGER_SIGN => false
 889                );
 890            }
 891
 892            $temp = $this->_subtract($x_value, false, $y_value, false);
 893            $temp[MATH_BIGINTEGER_SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
 894                                          $x_negative : $y_negative;
 895
 896            return $temp;
 897        }
 898
 899        if ($x_size < $y_size) {
 900            $size = $x_size;
 901            $value = $y_value;
 902        } else {
 903            $size = $y_size;
 904            $value = $x_value;
 905        }
 906
 907        $value[count($value)] = 0; // just in case the carry adds an extra digit
 908
 909        $carry = 0;
 910        for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
 911            $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] + $y_value[$j] * MATH_BIGINTEGER_BASE_FULL + $y_value[$i] + $carry;
 912            $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
 913            $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
 914
 915            $temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
 916
 917            $value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
 918            $value[$j] = $temp;
 919        }
 920
 921        if ($j == $size) { // ie. if $y_size is odd
 922            $sum = $x_value[$i] + $y_value[$i] + $carry;
 923            $carry = $sum >= MATH_BIGINTEGER_BASE_FULL;
 924            $value[$i] = $carry ? $sum - MATH_BIGINTEGER_BASE_FULL : $sum;
 925            ++$i; // ie. let $i = $j since we've just done $value[$i]
 926        }
 927
 928        if ($carry) {
 929            for (; $value[$i] == MATH_BIGINTEGER_MAX_DIGIT; ++$i) {
 930                $value[$i] = 0;
 931            }
 932            ++$value[$i];
 933        }
 934
 935        return array(
 936            MATH_BIGINTEGER_VALUE => $this->_trim($value),
 937            MATH_BIGINTEGER_SIGN => $x_negative
 938        );
 939    }
 940
 941    /**
 942     * Subtracts two BigIntegers.
 943     *
 944     * Here's an example:
 945     * <code>
 946     * <?php
 947     *    $a = new \PHPSecLib\Math\BigInteger('10');
 948     *    $b = new \PHPSecLib\Math\BigInteger('20');
 949     *
 950     *    $c = $a->subtract($b);
 951     *
 952     *    echo $c->toString(); // outputs -10
 953     * ?>
 954     * </code>
 955     *
 956     * @param \PHPSecLib\Math\BigInteger $y
 957     * @return \PHPSecLib\Math\BigInteger
 958     * @access public
 959     * @internal Performs base-2**52 subtraction
 960     */
 961    function subtract($y)
 962    {
 963        switch ( MATH_BIGINTEGER_MODE ) {
 964            case MATH_BIGINTEGER_MODE_GMP:
 965                $temp = new static();
 966                $temp->value = gmp_sub($this->value, $y->value);
 967
 968                return $this->_normalize($temp);
 969            case MATH_BIGINTEGER_MODE_BCMATH:
 970                $temp = new static();
 971                $temp->value = bcsub($this->value, $y->value, 0);
 972
 973                return $this->_normalize($temp);
 974        }
 975
 976        $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
 977
 978        $result = new static();
 979        $result->value = $temp[MATH_BIGINTEGER_VALUE];
 980        $result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
 981
 982        return $this->_normalize($result);
 983    }
 984
 985    /**
 986     * Performs subtraction.
 987     *
 988     * @param Array $x_value
 989     * @param Boolean $x_negative
 990     * @param Array $y_value
 991     * @param Boolean $y_negative
 992     * @return Array
 993     * @access private
 994     */
 995    function _subtract($x_value, $x_negative, $y_value, $y_negative)
 996    {
 997        $x_size = count($x_value);
 998        $y_size = count($y_value);
 999
1000        if ($x_size == 0) {
1001            return array(
1002                MATH_BIGINTEGER_VALUE => $y_value,
1003                MATH_BIGINTEGER_SIGN => !$y_negative
1004            );
1005        } else if ($y_size == 0) {
1006            return array(
1007                MATH_BIGINTEGER_VALUE => $x_value,
1008                MATH_BIGINTEGER_SIGN => $x_negative
1009            );
1010        }
1011
1012        // add, if appropriate (ie. -$x - +$y or +$x - -$y)
1013        if ( $x_negative != $y_negative ) {
1014            $temp = $this->_add($x_value, false, $y_value, false);
1015            $temp[MATH_BIGINTEGER_SIGN] = $x_negative;
1016
1017            return $temp;
1018        }
1019
1020        $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
1021
1022        if ( !$diff ) {
1023            return array(
1024                MATH_BIGINTEGER_VALUE => array(),
1025                MATH_BIGINTEGER_SIGN => false
1026            );
1027        }
1028
1029        // switch $x and $y around, if appropriate.
1030        if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) {
1031            $temp = $x_value;
1032            $x_value = $y_value;
1033            $y_value = $temp;
1034
1035            $x_negative = !$x_negative;
1036
1037            $x_size = count($x_value);
1038            $y_size = count($y_value);
1039        }
1040
1041        // at this point, $x_value should be at least as big as - if not bigger than - $y_value
1042
1043        $carry = 0;
1044        for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
1045            $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] - $y_value[$j] * MATH_BIGINTEGER_BASE_FULL - $y_value[$i] - $carry;
1046            $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
1047            $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
1048
1049            $temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
1050
1051            $x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp);
1052            $x_value[$j] = $temp;
1053        }
1054
1055        if ($j == $y_size) { // ie. if $y_size is odd
1056            $sum = $x_value[$i] - $y_value[$i] - $carry;
1057            $carry = $sum < 0;
1058            $x_value[$i] = $carry ? $sum + MATH_BIGINTEGER_BASE_FULL : $sum;
1059            ++$i;
1060        }
1061
1062        if ($carry) {
1063            for (; !$x_value[$i]; ++$i) {
1064                $x_value[$i] = MATH_BIGINTEGER_MAX_DIGIT;
1065            }
1066            --$x_value[$i];
1067        }
1068
1069        return array(
1070            MATH_BIGINTEGER_VALUE => $this->_trim($x_value),
1071            MATH_BIGINTEGER_SIGN => $x_negative
1072        );
1073    }
1074
1075    /**
1076     * Multiplies two BigIntegers
1077     *
1078     * Here's an example:
1079     * <code>
1080     * <?php
1081     *    $a = new \PHPSecLib\Math\BigInteger('10');
1082     *    $b = new \PHPSecLib\Math\BigInteger('20');
1083     *
1084     *    $c = $a->multiply($b);
1085     *
1086     *    echo $c->toString(); // outputs 200
1087     * ?>
1088     * </code>
1089     *
1090     * @param \PHPSecLib\Math\BigInteger $x
1091     * @return \PHPSecLib\Math\BigInteger
1092     * @access public
1093     */
1094    function multiply($x)
1095    {
1096        switch ( MATH_BIGINTEGER_MODE ) {
1097            case MATH_BIGINTEGER_MODE_GMP:
1098                $temp = new static();
1099                $temp->value = gmp_mul($this->value, $x->value);
1100
1101                return $this->_normalize($temp);
1102            case MATH_BIGINTEGER_MODE_BCMATH:
1103                $temp = new static();
1104                $temp->value = bcmul($this->value, $x->value, 0);
1105
1106                return $this->_normalize($temp);
1107        }
1108
1109        $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
1110
1111        $product = new static();
1112        $product->value = $temp[MATH_BIGINTEGER_VALUE];
1113        $product->is_negative = $temp[MATH_BIGINTEGER_SIGN];
1114
1115        return $this->_normalize($product);
1116    }
1117
1118    /**
1119     * Performs multiplication.
1120     *
1121     * @param Array $x_value
1122     * @param Boolean $x_negative
1123     * @param Array $y_value
1124     * @param Boolean $y_negative
1125     * @return Array
1126     * @access private
1127     */
1128    function _multiply($x_value, $x_negative, $y_value, $y_negative)
1129    {
1130        //if ( $x_value == $y_value ) {
1131        //    return array(
1132        //        MATH_BIGINTEGER_VALUE => $this->_square($x_value),
1133        //        MATH_BIGINTEGER_SIGN => $x_sign != $y_value
1134        //    );
1135        //}
1136
1137        $x_length = count($x_value);
1138        $y_length = count($y_value);
1139
1140        if ( !$x_length || !$y_length ) { // a 0 is being multiplied
1141            return array(
1142                MATH_BIGINTEGER_VALUE => array(),
1143                MATH_BIGINTEGER_SIGN => false
1144            );
1145        }
1146
1147        return array(
1148            MATH_BIGINTEGER_VALUE => min($x_length, $y_length) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
1149                $this->_trim($this->_regularMultiply($x_value, $y_value)) :
1150                $this->_trim($this->_karatsuba($x_value, $y_value)),
1151            MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
1152        );
1153    }
1154
1155    /**
1156     * Performs long multiplication on two BigIntegers
1157     *
1158     * Modeled after 'multiply' in MutableBigInteger.java.
1159     *
1160     * @param Array $x_value
1161     * @param Array $y_value
1162     * @return Array
1163     * @access private
1164     */
1165    function _regularMultiply($x_value, $y_value)
1166    {
1167        $x_length = count($x_value);
1168        $y_length = count($y_value);
1169
1170        if ( !$x_length || !$y_length ) { // a 0 is being multiplied
1171            return array();
1172        }
1173
1174        if ( $x_length < $y_length ) {
1175            $temp = $x_value;
1176            $x_value = $y_value;
1177            $y_value = $temp;
1178
1179            $x_length = count($x_value);
1180            $y_length = count($y_value);
1181        }
1182
1183        $product_value = $this->_array_repeat(0, $x_length + $y_length);
1184
1185        // the following for loop could be removed if the for loop following it
1186        // (the one with nested for loops) initially set $i to 0, but
1187        // doing so would also make the result in one set of unnecessary adds,
1188        // since on the outermost loops first pass, $product->value[$k] is going
1189        // to always be 0
1190
1191        $carry = 0;
1192
1193        for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
1194            $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
1195            $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1196            $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
1197        }
1198
1199        $product_value[$j] = $carry;
1200
1201        // the above for loop is what the previous comment was talking about.  the
1202        // following for loop is the "one with nested for loops"
1203        for ($i = 1; $i < $y_length; ++$i) {
1204            $carry = 0;
1205
1206            for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
1207                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
1208                $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1209                $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
1210            }
1211
1212            $product_value[$k] = $carry;
1213        }
1214
1215        return $product_value;
1216    }
1217
1218    /**
1219     * Performs Karatsuba multiplication on two BigIntegers
1220     *
1221     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1222     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
1223     *
1224     * @param Array $x_value
1225     * @param Array $y_value
1226     * @return Array
1227     * @access private
1228     */
1229    function _karatsuba($x_value, $y_value)
1230    {
1231        $m = min(count($x_value) >> 1, count($y_value) >> 1);
1232
1233        if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
1234            return $this->_regularMultiply($x_value, $y_value);
1235        }
1236
1237        $x1 = array_slice($x_value, $m);
1238        $x0 = array_slice($x_value, 0, $m);
1239        $y1 = array_slice($y_value, $m);
1240        $y0 = array_slice($y_value, 0, $m);
1241
1242        $z2 = $this->_karatsuba($x1, $y1);
1243        $z0 = $this->_karatsuba($x0, $y0);
1244
1245        $z1 = $this->_add($x1, false, $x0, false);
1246        $temp = $this->_add($y1, false, $y0, false);
1247        $z1 = $this->_karatsuba($z1[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_VALUE]);
1248        $temp = $this->_add($z2, false, $z0, false);
1249        $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
1250
1251        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
1252        $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
1253
1254        $xy = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
1255        $xy = $this->_add($xy[MATH_BIGINTEGER_VALUE], $xy[MATH_BIGINTEGER_SIGN], $z0, false);
1256
1257        return $xy[MATH_BIGINTEGER_VALUE];
1258    }
1259
1260    /**
1261     * Performs squaring
1262     *
1263     * @param Array $x
1264     * @return Array
1265     * @access private
1266     */
1267    function _square($x = false)
1268    {
1269        return count($x) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
1270            $this->_trim($this->_baseSquare($x)) :
1271            $this->_trim($this->_karatsubaSquare($x));
1272    }
1273
1274    /**
1275     * Performs traditional squaring on two BigIntegers
1276     *
1277     * Squaring can be done faster than multiplying a number by itself can be.  See
1278     * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
1279     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
1280     *
1281     * @param Array $value
1282     * @return Array
1283     * @access private
1284     */
1285    function _baseSquare($value)
1286    {
1287        if ( empty($value) ) {
1288            return array();
1289        }
1290        $square_value = $this->_array_repeat(0, 2 * count($value));
1291
1292        for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
1293            $i2 = $i << 1;
1294
1295            $temp = $square_value[$i2] + $value[$i] * $value[$i];
1296            $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1297            $square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
1298
1299            // note how we start from $i+1 instead of 0 as we do in multiplication.
1300            for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
1301                $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
1302                $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
1303                $square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
1304            }
1305
1306            // the following line can yield values larger 2**15.  at this point, PHP should switch
1307            // over to floats.
1308            $square_value[$i + $max_index + 1] = $carry;
1309        }
1310
1311        return $square_value;
1312    }
1313
1314    /**
1315     * Performs Karatsuba "squaring" on two BigIntegers
1316     *
1317     * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1318     * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
1319     *
1320     * @param Array $value
1321     * @return Array
1322     * @access private
1323     */
1324    function _karatsubaSquare($value)
1325    {
1326        $m = count($value) >> 1;
1327
1328        if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
1329            return $this->_baseSquare($value);
1330        }
1331
1332        $x1 = array_slice($value, $m);
1333        $x0 = array_slice($value, 0, $m);
1334
1335        $z2 = $this->_karatsubaSquare($x1);
1336        $z0 = $this->_karatsubaSquare($x0);
1337
1338        $z1 = $this->_add($x1, false, $x0, false);
1339        $z1 = $this->_karatsubaSquare($z1[MATH_BIGINTEGER_VALUE]);
1340        $temp = $this->_add($z2, false, $z0, false);
1341        $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
1342
1343        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
1344        $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
1345
1346        $xx = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
1347        $xx = $this->_add($xx[MATH_BIGINTEGER_VALUE], $xx[MATH_BIGINTEGER_SIGN], $z0, false);
1348
1349        return $xx[MATH_BIGINTEGER_VALUE];
1350    }
1351
1352    /**
1353     * Divides two BigIntegers.
1354     *
1355     * Returns an array whose first element contains the quotient and whose second element contains the
1356     * "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
1357     * same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
1358     * and the divisor (basically, the "common residue" is the first positive modulo).
1359     *
1360     * Here's an example:
1361     * <code>
1362     * <?php
1363     *    $a = new \PHPSecLib\Math\BigInteger('10');
1364     *    $b = new \PHPSecLib\Math\BigInteger('20');
1365     *
1366     *    list($quotient, $remainder) = $a->divide($b);
1367     *
1368     *    echo $quotient->toString(); // outputs 0
1369     *    echo "\r\n";
1370     *    echo $remainder->toString(); // outputs 10
1371     * ?>
1372     * </code>
1373     *
1374     * @param \PHPSecLib\Math\BigInteger $y
1375     * @return Array
1376     * @access public
1377     * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
1378     */
1379    function divide($y)
1380    {
1381        switch ( MATH_BIGINTEGER_MODE ) {
1382            case MATH_BIGINTEGER_MODE_GMP:
1383                $quotient = new static();
1384                $remainder = new static();
1385
1386                list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
1387
1388                if (gmp_sign($remainder->value) < 0) {
1389                    $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
1390                }
1391
1392                return array($this->_normalize($quotient), $this->_normalize($remainder));
1393            case MATH_BIGINTEGER_MODE_BCMATH:
1394                $quotient = new static();
1395                $remainder = new static();
1396
1397                $quotient->value = bcdiv($this->value, $y->value, 0);
1398                $remainder->value = bcmod($this->value, $y->value);
1399
1400                if ($remainder->value[0] == '-') {
1401                    $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0);
1402                }
1403
1404                return array($this->_normalize($quotient), $this->_normalize($remainder));
1405        }
1406
1407        if (count($y->value) == 1) {
1408            list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
1409            $quotient = new static();
1410            $remainder = new static();
1411            $quotient->value = $q;
1412            $remainder->value = array($r);
1413            $quotient->is_negative = $this->is_negative != $y->is_negative;
1414            return array($this->_normalize($quotient), $this->_normalize($remainder));
1415        }
1416
1417        static $zero;
1418        if ( !isset($zero) ) {
1419            $zero = new static();
1420        }
1421
1422        $x = $this->copy();
1423        $y = $y->copy();
1424
1425        $x_sign = $x->is_negative;
1426        $y_sign = $y->is_negative;
1427
1428        $x->is_negative = $y->is_negative = false;
1429
1430        $diff = $x->compare($y);
1431
1432        if ( !$diff ) {
1433            $temp = new static();
1434            $temp->value = array(1);
1435            $temp->is_negative = $x_sign != $y_sign;
1436            return array($this->_normalize($temp), $this->_normalize(new static()));
1437        }
1438
1439        if ( $diff < 0 ) {
1440            // if $x is negative, "add" $y.
1441            if ( $x_sign ) {
1442                $x = $y->subtract($x);
1443            }
1444            return array($this->_normalize(new static()), $this->_normalize($x));
1445        }
1446
1447        // normalize $x and $y as described in HAC 14.23 / 14.24
1448        $msb = $y->value[count($y->value) - 1];
1449        for ($shift = 0; !($msb & MATH_BIGINTEGER_MSB); ++$shift) {
1450            $msb <<= 1;
1451        }
1452        $x->_lshift($shift);
1453        $y->_lshift($shift);
1454        $y_value = &$y->value;
1455
1456        $x_max = count($x->value) - 1;
1457        $y_max = count($y->value) - 1;
1458
1459        $quotient = new static();
1460  

Large files files are truncated, but you can click here to view the full file