Failed Conditions
Push — PHPSecLib_Rid ( 32d4bc...6a2b08 )
by Florent
09:40
created

BigInteger::__construct()   D

Complexity

Conditions 27
Paths 65

Size

Total Lines 95
Code Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 2 Features 0
Metric Value
c 5
b 2
f 0
dl 0
loc 95
rs 4.509
cc 27
eloc 61
nc 65
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace Jose\Util;
13
14
final class BigInteger
15
{
16
    /**
17
     * Holds the BigInteger's value.
18
     *
19
     * @var resource
20
     */
21
    private $value;
22
23
    /**
24
     * Holds the BigInteger's magnitude.
25
     *
26
     * @var bool
27
     */
28
    private $is_negative = false;
29
30
    /**
31
     * Precision.
32
     */
33
    private $precision = -1;
34
35
    /**
36
     * Precision Bitmask.
37
     */
38
    private $bitmask = false;
39
40
    /**
41
     * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
42
     *
43
     * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
44
     * two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
45
     *
46
     * Here's an example:
47
     * <code>
48
     * <?php
49
     *    $a = new \Jose\Util\in base-16
50
     *
51
     *    echo $a->toString(); // outputs 50
52
     * ?>
53
     * </code>
54
     *
55
     * @param $x base-10 number or base-$base number if $base set.
56
     * @param int $base
57
     */
58
    public function __construct($x = 0, $base = 10)
59
    {
60
        if(is_resource($x) && get_resource_type($x) == 'GMP integer') {
61
            $this->value = $x;
62
            
63
            return;
64
        }
65
        
66
        $this->value = gmp_init(0);
0 ignored issues
show
Documentation Bug introduced by
It seems like gmp_init(0) of type object<GMP> is incompatible with the declared type resource of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
67
68
        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
69
        // '0' is the only value like this per http://php.net/empty
70
        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $x (integer) and '0' (string) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
71
            return;
72
        }
73
74
        switch ($base) {
75
            case -256:
76
                if (ord($x[0]) & 0x80) {
77
                    $x = ~$x;
78
                    $this->is_negative = true;
79
                }
80
            case 256:
81
                $sign = $this->is_negative ? '-' : '';
82
                $this->value = gmp_init($sign.'0x'.bin2hex($x));
0 ignored issues
show
Documentation Bug introduced by
It seems like gmp_init($sign . '0x' . bin2hex($x)) of type object<GMP> is incompatible with the declared type resource of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
83
84
                if ($this->is_negative) {
85
                    $this->is_negative = false;
86
                    $temp = $this->add(new static('-1'));
87
                    $this->value = $temp->value;
88
                }
89
                break;
90
            case 16:
91
            case -16:
92
                if ($base > 0 && $x[0] == '-') {
93
                    $this->is_negative = true;
94
                    $x = substr($x, 1);
95
                }
96
97
                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
98
99
                $is_negative = false;
100
                if ($base < 0 && hexdec($x[0]) >= 8) {
101
                    $this->is_negative = $is_negative = true;
102
                    $x = bin2hex(~hex2bin($x));
103
                }
104
105
            $temp = $this->is_negative ? '-0x'.$x : '0x'.$x;
106
            $this->value = gmp_init($temp);
0 ignored issues
show
Documentation Bug introduced by
It seems like gmp_init($temp) of type object<GMP> is incompatible with the declared type resource of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
107
            $this->is_negative = false;
108
109
                if ($is_negative) {
110
                    $temp = $this->add(new static('-1'));
111
                    $this->value = $temp->value;
112
                }
113
                break;
114
            case 10:
115
            case -10:
116
                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
117
                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
118
                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
119
                $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
120
121
                $this->value = gmp_init($x);
0 ignored issues
show
Documentation Bug introduced by
It seems like gmp_init($x) of type object<GMP> is incompatible with the declared type resource of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
122
                break;
123
            case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
124
            case -2:
125
                if ($base > 0 && $x[0] == '-') {
126
                    $this->is_negative = true;
127
                    $x = substr($x, 1);
128
                }
129
130
                $x = preg_replace('#^([01]*).*#', '$1', $x);
131
                $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
132
133
                $str = '0x';
134
                while (strlen($x)) {
135
                    $part = substr($x, 0, 4);
136
                    $str .= dechex(bindec($part));
137
                    $x = substr($x, 4);
138
                }
139
140
                if ($this->is_negative) {
141
                    $str = '-'.$str;
142
                }
143
144
                $temp = new static($str, 8 * $base); // ie. either -16 or +16
145
                $this->value = $temp->value;
146
                $this->is_negative = $temp->is_negative;
147
148
                break;
149
            default:
150
                // base not supported, so we'll let $this == 0
151
        }
152
    }
153
154
    /**
155
     * Converts a BigInteger to a byte string (eg. base-256).
156
     *
157
     * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
158
     * saved as two's compliment.
159
     *
160
     * Here's an example:
161
     * <code>
162
     * <?php
163
     *    $a = new \Jose\Util\ger('65');
164
     *
165
     *    echo $a->toBytes(); // outputs chr(65)
166
     * ?>
167
     * </code>
168
     *
169
     * @param bool $twos_compliment
170
     *
171
     * @return string
172
     *
173
     */
174
    public function toBytes($twos_compliment = false)
175
    {
176
        if ($twos_compliment) {
177
            $comparison = $this->compare(new static());
178
            if ($comparison == 0) {
179
                return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
180
            }
181
182
            $temp = $comparison < 0 ? $this->add(new static(1)) : $this;
183
            $bytes = $temp->toBytes();
184
185
            if (empty($bytes)) { // eg. if the number we're trying to convert is -1
186
                $bytes = chr(0);
187
            }
188
189
            if (ord($bytes[0]) & 0x80) {
190
                $bytes = chr(0).$bytes;
191
            }
192
193
            return $comparison < 0 ? ~$bytes : $bytes;
194
        }
195
196
        if (gmp_cmp($this->value, gmp_init(0)) == 0) {
197
            return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
198
        }
199
200
        $temp = gmp_strval(gmp_abs($this->value), 16);
201
        $temp = (strlen($temp) & 1) ? '0'.$temp : $temp;
202
        $temp = hex2bin($temp);
203
204
        return $this->precision > 0 ?
205
            substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
206
            ltrim($temp, chr(0));
207
    }
208
209
    /**
210
     * Adds two BigIntegers.
211
     *
212
     * Here's an example:
213
     * <code>
214
     * <?php
215
     *    $a = new \Jose\Util\ger('10');
216
     *    $b = new \Jose\Util\ger('20');
217
     *
218
     *    $c = $a->add($b);
219
     *
220
     *    echo $c->toString(); // outputs 30
221
     * ?>
222
     * </code>
223
     *
224
     * @param \Jose\Util\BigInteger $y
225
     *
226
     * @return \Jose\Util\BigInteger
227
     *
228
     */
229
    public function add(BigInteger $y)
230
    {
231
        $temp = new static();
232
        $temp->value = gmp_add($this->value, $y->value);
233
234
        return $this->_normalize($temp);
235
    }
236
237
    /**
238
     * Subtracts two BigIntegers.
239
     *
240
     * Here's an example:
241
     * <code>
242
     * <?php
243
     *    $a = new \Jose\Util\ger('10');
244
     *    $b = new \Jose\Util\ger('20');
245
     *
246
     *    $c = $a->subtract($b);
247
     *
248
     *    echo $c->toString(); // outputs -10
249
     * ?>
250
     * </code>
251
     *
252
     * @param \Jose\Util\BigInteger $y
253
     *
254
     * @return \Jose\Util\BigInteger
255
     *
256
     */
257
    public function subtract(BigInteger $y)
258
    {
259
        $temp = new static();
260
        $temp->value = gmp_sub($this->value, $y->value);
261
262
        return $this->_normalize($temp);
263
    }
264
265
    /**
266
     * Multiplies two BigIntegers.
267
     *
268
     * Here's an example:
269
     * <code>
270
     * <?php
271
     *    $a = new \Jose\Util\ger('10');
272
     *    $b = new \Jose\Util\ger('20');
273
     *
274
     *    $c = $a->multiply($b);
275
     *
276
     *    echo $c->toString(); // outputs 200
277
     * ?>
278
     * </code>
279
     *
280
     * @param \Jose\Util\BigInteger $x
281
     *
282
     * @return \Jose\Util\BigInteger
283
     */
284
    public function multiply(BigInteger $x)
285
    {
286
        $temp = new static();
287
        $temp->value = gmp_mul($this->value, $x->value);
288
289
        return $this->_normalize($temp);
290
    }
291
292
    /**
293
     * Divides two BigIntegers.
294
     *
295
     * Returns an array whose first element contains the quotient and whose second element contains the
296
     * "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
297
     * same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
298
     * and the divisor (basically, the "common residue" is the first positive modulo).
299
     *
300
     * Here's an example:
301
     * <code>
302
     * <?php
303
     *    $a = new \Jose\Util\ger('10');
304
     *    $b = new \Jose\Util\ger('20');
305
     *
306
     *    list($quotient, $remainder) = $a->divide($b);
307
     *
308
     *    echo $quotient->toString(); // outputs 0
309
     *    echo "\r\n";
310
     *    echo $remainder->toString(); // outputs 10
311
     * ?>
312
     * </code>
313
     * @param \Jose\Util\BigInteger $y
314
     *
315
     * @return \Jose\Util\BigInteger[]
316
     *
317
     */
318
    public function divide(BigInteger $y)
319
    {
320
        $quotient = new static();
321
        $remainder = new static();
322
323
        list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
324
325
        if (gmp_sign($remainder->value) < 0) {
326
            $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
327
        }
328
329
        return [$this->_normalize($quotient), $this->_normalize($remainder)];
330
    }
331
332
    /**
333
     * Performs modular exponentiation.
334
     *
335
     * Here's an example:
336
     * <code>
337
     * <?php
338
     *    $a = new \Jose\Util\ger('10');
339
     *    $b = new \Jose\Util\ger('20');
340
     *    $c = new \Jose\Util\ger('30');
341
     *
342
     *    $c = $a->modPow($b, $c);
343
     *
344
     *    echo $c->toString(); // outputs 10
345
     * ?>
346
     * </code>
347
     *
348
     * @param \Jose\Util\BigInteger $e
349
     * @param \Jose\Util\BigInteger $n
350
     *
351
     * @return \Jose\Util\BigInteger
352
     *
353
     *    and although the approach involving repeated squaring does vastly better, it, too, is impractical
354
     *    for our purposes.  The reason being that division - by far the most complicated and time-consuming
355
     *    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
356
     *
357
     *    Modular reductions resolve this issue.  Although an individual modular reduction takes more time
358
     *    then an individual division, when performed in succession (with the same modulo), they're a lot faster.
359
     *
360
     *    The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,
361
     *    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the
362
     *    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
363
     *    the product of two odd numbers is odd), but what about when RSA isn't used?
364
     *
365
     *    In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a
366
     *    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the
367
     *    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,
368
     *    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
369
     *    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.
370
     *    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
371
     */
372
    public function modPow(BigInteger $e, BigInteger $n)
373
    {
374
        $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
0 ignored issues
show
Bug introduced by
The method compare cannot be called on $this->bitmask (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
375
376
        if ($e->compare(new static()) < 0) {
377
            $e = $e->abs();
378
379
            $temp = $this->modInverse($n);
0 ignored issues
show
Bug introduced by
It seems like $n defined by $this->bitmask !== false...is->bitmask : $n->abs() on line 374 can also be of type boolean; however, Jose\Util\BigInteger::modInverse() does only seem to accept object<Jose\Util\BigInteger>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
380
            if ($temp === false) {
381
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by Jose\Util\BigInteger::modPow of type Jose\Util\BigInteger.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
382
            }
383
384
            return $this->_normalize($temp->modPow($e, $n));
0 ignored issues
show
Bug introduced by
It seems like $n defined by $this->bitmask !== false...is->bitmask : $n->abs() on line 374 can also be of type boolean; however, Jose\Util\BigInteger::modPow() does only seem to accept object<Jose\Util\BigInteger>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
385
        }
386
387
            $temp = new static();
388
            $temp->value = gmp_powm($this->value, $e->value, $n->value);
389
390
            return $this->_normalize($temp);
391
    }
392
393
    /**
394
     * Calculates modular inverses.
395
     *
396
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
397
     *
398
     * Here's an example:
399
     * <code>
400
     * <?php
401
     *    $a = new \Jose\Util\teger(30);
402
     *    $b = new \Jose\Util\teger(17);
403
     *
404
     *    $c = $a->modInverse($b);
405
     *    echo $c->toString(); // outputs 4
406
     *
407
     *    echo "\r\n";
408
     *
409
     *    $d = $a->multiply($c);
410
     *    list(, $d) = $d->divide($b);
411
     *    echo $d; // outputs 1 (as per the definition of modular inverse)
412
     * ?>
413
     * </code>
414
     *
415
     * @param \Jose\Util\BigInteger $n
416
     *
417
     * @return \Jose\Util\BigInteger|bool
418
     *
419
     */
420
    public function modInverse(BigInteger $n)
421
    {
422
        $temp = new static();
423
        $temp->value = gmp_invert($this->value, $n->value);
424
425
        return ($temp->value === false) ? false : $this->_normalize($temp);
426
    }
427
428
    /**
429
     * Absolute value.
430
     *
431
     * @return \Jose\Util\BigInteger
432
     */
433
    public function abs()
434
    {
435
        $temp = new static();
436
437
        $temp->value = gmp_abs($this->value);
438
439
        return $temp;
440
    }
441
442
    /**
443
     * Compares two numbers.
444
     *
445
     * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
446
     * demonstrated thusly:
447
     *
448
     * $x  > $y: $x->compare($y)  > 0
449
     * $x  < $y: $x->compare($y)  < 0
450
     * $x == $y: $x->compare($y) == 0
451
     *
452
     * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
453
     *
454
     * @param \Jose\Util\BigInteger $y
455
     *
456
     * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
457
     *
458
     */
459
    public function compare(BigInteger $y)
460
    {
461
        return gmp_cmp($this->value, $y->value);
462
    }
463
464
    /**
465
     * Logical Left Shift.
466
     *
467
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
468
     *
469
     * @param int $shift
470
     *
471
     * @return \Jose\Util\BigInteger
472
     *
473
     */
474
    public function bitwise_leftShift($shift)
475
    {
476
        $temp = new static();
477
478
        static $two;
479
480
        if (!isset($two)) {
481
            $two = gmp_init('2');
482
        }
483
484
        $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
485
486
        return $this->_normalize($temp);
487
    }
488
489
    /**
490
     * Generates a random BigInteger.
491
     *
492
     * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
493
     *
494
     * @param int $size
495
     *
496
     * @return \Jose\Util\BigInteger
497
     */
498
    private static function _random_number_helper($size)
499
    {
500
        return new static(random_bytes($size), 256);
501
    }
502
503
    /**
504
     * Generate a random number.
505
     *
506
     * Returns a random number between $min and $max where $min and $max
507
     * can be defined using one of the two methods:
508
     *
509
     * BigInteger::random($min, $max)
510
     * BigInteger::random($max, $min)
511
     *
512
     * @param \Jose\Util\BigInteger $min
513
     * @param \Jose\Util\BigInteger $max
514
     *
515
     * @return \Jose\Util\BigInteger
516
     */
517
    public static function random(BigInteger $min, BigInteger $max)
518
    {
519
        $compare = $max->compare($min);
520
521
        if (!$compare) {
522
            return $this->_normalize($min);
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
Usage of "$this" in static methods will cause runtime errors
Loading history...
523
        } elseif ($compare < 0) {
524
            // if $min is bigger then $max, swap $min and $max
525
            $temp = $max;
526
            $max = $min;
527
            $min = $temp;
528
        }
529
530
        static $one;
531
        if (!isset($one)) {
532
            $one = new static(1);
533
        }
534
535
        $max = $max->subtract($min->subtract($one));
536
        $size = strlen(ltrim($max->toBytes(), chr(0)));
537
538
        /*
539
            doing $random % $max doesn't work because some numbers will be more likely to occur than others.
540
            eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
541
            would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
542
            not all numbers would be equally likely. some would be more likely than others.
543
544
            creating a whole new random number until you find one that is within the range doesn't work
545
            because, for sufficiently small ranges, the likelihood that you'd get a number within that range
546
            would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
547
            would be pretty high that $random would be greater than $max.
548
549
            phpseclib works around this using the technique described here:
550
551
            http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
552
        */
553
        $random_max = new static(chr(1).str_repeat("\0", $size), 256);
554
        $random = self::_random_number_helper($size);
555
556
        list($max_multiple) = $random_max->divide($max);
557
        $max_multiple = $max_multiple->multiply($max);
558
559
        while ($random->compare($max_multiple) >= 0) {
560
            $random = $random->subtract($max_multiple);
561
            $random_max = $random_max->subtract($max_multiple);
562
            $random = $random->bitwise_leftShift(8);
563
            $random = $random->add(self::_random_number_helper(1));
564
            $random_max = $random_max->bitwise_leftShift(8);
565
            list($max_multiple) = $random_max->divide($max);
566
            $max_multiple = $max_multiple->multiply($max);
567
        }
568
        list(, $random) = $random->divide($max);
569
570
        return $random->add($min);
571
    }
572
573
    /**
574
     * Normalize.
575
     *
576
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
577
     *
578
     * @param \Jose\Util\BigInteger $result
579
     *
580
     * @return \Jose\Util\BigInteger
581
     */
582
    private function _normalize($result)
583
    {
584
        $result->precision = $this->precision;
585
        $result->bitmask = $this->bitmask;
586
587
        if ($this->bitmask !== false) {
588
            $result->value = gmp_and($result->value, $result->bitmask->value);
589
        }
590
591
        return $result;
592
    }
593
}
594