GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 95c197...564e5e )
by Joni
04:32
created

Integer   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 54
dl 0
loc 158
ccs 57
cts 57
cp 1
rs 10
c 0
b 0
f 0
wmc 22

8 Methods

Rating   Name   Duplication   Size   Complexity  
A _encodedContentDER() 0 13 3
A intNumber() 0 3 1
A _decodeFromDER() 0 24 4
A _validateNumber() 0 9 4
A _encodePositiveInteger() 0 9 2
A number() 0 3 1
A __construct() 0 8 3
A _encodeNegativeInteger() 0 21 4
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\ASN1\Type\Primitive;
6
7
use Sop\ASN1\Component\Identifier;
8
use Sop\ASN1\Component\Length;
9
use Sop\ASN1\Element;
10
use Sop\ASN1\Feature\ElementBase;
11
use Sop\ASN1\Type\PrimitiveType;
12
use Sop\ASN1\Type\UniversalClass;
13
use Sop\ASN1\Util\BigInt;
14
15
/**
16
 * Implements *INTEGER* type.
17
 */
18
class Integer extends Element
19
{
20
    use UniversalClass;
21
    use PrimitiveType;
22
23
    /**
24
     * The number.
25
     *
26
     * @var BigInt
27
     */
28
    private $_number;
29
30
    /**
31
     * Constructor.
32
     *
33
     * @param int|string $number Base 10 integer
34
     */
35 69
    public function __construct($number)
36
    {
37 69
        $this->_typeTag = self::TYPE_INTEGER;
38 69
        if (!self::_validateNumber($number)) {
39 2
            $var = is_scalar($number) ? strval($number) : gettype($number);
40 2
            throw new \InvalidArgumentException("'{$var}' is not a valid number.");
41
        }
42 67
        $this->_number = new BigInt($number);
43 67
    }
44
45
    /**
46
     * Get the number as a base 10.
47
     *
48
     * @return string Integer as a string
49
     */
50 24
    public function number(): string
51
    {
52 24
        return $this->_number->base10();
53
    }
54
55
    /**
56
     * Get the number as an integer type.
57
     *
58
     * @return int
59
     */
60 6
    public function intNumber(): int
61
    {
62 6
        return $this->_number->intVal();
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 31
    protected function _encodedContentDER(): string
69
    {
70 31
        $num = $this->_number->gmpObj();
71 31
        switch (gmp_sign($num)) {
72
            // positive
73 31
            case 1:
74 14
                return self::_encodePositiveInteger($num);
75
            // negative
76
            case -1:
77 15
                return self::_encodeNegativeInteger($num);
78
        }
79
        // zero
80 2
        return "\0";
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 36
    protected static function _decodeFromDER(Identifier $identifier,
87
        string $data, int &$offset): ElementBase
88
    {
89 36
        $idx = $offset;
90 36
        $length = Length::expectFromDER($data, $idx)->intLength();
91 35
        $bytes = substr($data, $idx, $length);
92 35
        $idx += $length;
93 35
        $neg = ord($bytes[0]) & 0x80;
94
        // negative, apply inversion of two's complement
95 35
        if ($neg) {
96 15
            $len = strlen($bytes);
97 15
            for ($i = 0; $i < $len; ++$i) {
98 15
                $bytes[$i] = ~$bytes[$i];
99
            }
100
        }
101 35
        $num = gmp_init(bin2hex($bytes), 16);
102
        // negative, apply addition of two's complement
103
        // and produce negative result
104 35
        if ($neg) {
105 15
            $num = gmp_neg($num + 1);
106
        }
107 35
        $offset = $idx;
108
        // late static binding since enumerated extends integer type
109 35
        return new static(gmp_strval($num, 10));
110
    }
111
112
    /**
113
     * Encode positive integer to DER content.
114
     *
115
     * @param \GMP $num
116
     *
117
     * @return string
118
     */
119 14
    private static function _encodePositiveInteger(\GMP $num): string
120
    {
121 14
        $bin = gmp_export($num, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
122
        // if first bit is 1, prepend full zero byte
123
        // to represent positive two's complement
124 14
        if (ord($bin[0]) & 0x80) {
125 3
            $bin = chr(0x00) . $bin;
126
        }
127 14
        return $bin;
128
    }
129
130
    /**
131
     * Encode negative integer to DER content.
132
     *
133
     * @param \GMP $num
134
     *
135
     * @return string
136
     */
137 15
    private static function _encodeNegativeInteger(\GMP $num): string
138
    {
139 15
        $num = gmp_abs($num);
140
        // compute number of bytes required
141 15
        $width = 1;
142 15
        if ($num > 128) {
143 11
            $tmp = $num;
144
            do {
145 11
                ++$width;
146 11
                $tmp >>= 8;
147 11
            } while ($tmp > 128);
148
        }
149
        // compute two's complement 2^n - x
150 15
        $num = gmp_pow('2', 8 * $width) - $num;
151 15
        $bin = gmp_export($num, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
152
        // if first bit is 0, prepend full inverted byte
153
        // to represent negative two's complement
154 15
        if (!(ord($bin[0]) & 0x80)) {
155 1
            $bin = chr(0xff) . $bin;
156
        }
157 15
        return $bin;
158
    }
159
160
    /**
161
     * Test that number is valid for this context.
162
     *
163
     * @param mixed $num
164
     *
165
     * @return bool
166
     */
167 69
    private static function _validateNumber($num): bool
168
    {
169 69
        if (is_int($num)) {
170 28
            return true;
171
        }
172 41
        if (is_string($num) && preg_match('/-?\d+/', $num)) {
173 39
            return true;
174
        }
175 2
        return false;
176
    }
177
}
178