aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/phpseclib/phpseclib2_compat/src/Math/BigInteger.php
blob: 905d8fe65736cfcf09f3be753c2157adcb3f0bc9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
<?php

/**
 * Pure-PHP arbitrary precision integer arithmetic library.
 *
 * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,
 * and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
 * {@link self::MODE_INTERNAL self::MODE_INTERNAL} mode)
 *
 * BigInteger uses base-2**26 to perform operations such as multiplication and division and
 * base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction.  Because the largest possible
 * value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
 * point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
 * used.  As a consequence, bitwise operators such as >> 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:
 * <code>
 * <?php
 *    $a = new \phpseclib\Math\BigInteger(2);
 *    $b = new \phpseclib\Math\BigInteger(3);
 *
 *    $c = $a->add($b);
 *
 *    echo $c->toString(); // outputs 5
 * ?>
 * </code>
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @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 <terrafrost@php.net>
 * @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:
     * <code>
     * <?php
     *    $a = new \phpseclib\Math\BigInteger('0x32', 16); // 50 in base-16
     *
     *    echo $a->toString(); // outputs 50
     * ?>
     * </code>
     *
     * @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;
    }
}