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.

ObjectIdentifier::_decodeSubIDs()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 5
nop 1
dl 0
loc 22
ccs 16
cts 16
cp 1
crap 5
rs 9.4555
c 0
b 0
f 0
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\Exception\DecodeException;
11
use Sop\ASN1\Feature\ElementBase;
12
use Sop\ASN1\Type\PrimitiveType;
13
use Sop\ASN1\Type\UniversalClass;
14
15
/**
16
 * Implements *OBJECT IDENTIFIER* type.
17
 */
18
class ObjectIdentifier extends Element
19
{
20
    use UniversalClass;
21
    use PrimitiveType;
22
23
    /**
24
     * Object identifier in dotted format.
25
     *
26
     * @var string
27
     */
28
    protected $_oid;
29
30
    /**
31
     * Object identifier split to sub ID's.
32
     *
33
     * @var \GMP[]
34
     */
35
    protected $_subids;
36
37
    /**
38
     * Constructor.
39
     *
40
     * @param string $oid OID in dotted format
41
     */
42 28
    public function __construct(string $oid)
43
    {
44 28
        $this->_oid = $oid;
45 28
        $this->_subids = self::_explodeDottedOID($oid);
46
        // if OID is non-empty
47 27
        if (count($this->_subids) > 0) {
48
            // check that at least two nodes are set
49 25
            if (count($this->_subids) < 2) {
50 1
                throw new \UnexpectedValueException(
51 1
                    'OID must have at least two nodes.');
52
            }
53
            // check that root arc is in 0..2 range
54 24
            if ($this->_subids[0] > 2) {
55 1
                throw new \UnexpectedValueException(
56 1
                    'Root arc must be in range of 0..2.');
57
            }
58
            // if root arc is 0 or 1, second node must be in 0..39 range
59 23
            if ($this->_subids[0] < 2 && $this->_subids[1] >= 40) {
60 2
                throw new \UnexpectedValueException(
61 2
                    'Second node must be in 0..39 range for root arcs 0 and 1.');
62
            }
63
        }
64 23
        $this->_typeTag = self::TYPE_OBJECT_IDENTIFIER;
65 23
    }
66
67
    /**
68
     * Get OID in dotted format.
69
     */
70 19
    public function oid(): string
71
    {
72 19
        return $this->_oid;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 13
    protected function _encodedContentDER(): string
79
    {
80 13
        $subids = $this->_subids;
81
        // encode first two subids to one according to spec section 8.19.4
82 13
        if (count($subids) >= 2) {
83 12
            $num = ($subids[0] * 40) + $subids[1];
84 12
            array_splice($subids, 0, 2, [$num]);
85
        }
86 13
        return self::_encodeSubIDs(...$subids);
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92 21
    protected static function _decodeFromDER(Identifier $identifier,
93
        string $data, int &$offset): ElementBase
94
    {
95 21
        $idx = $offset;
96 21
        $len = Length::expectFromDER($data, $idx)->intLength();
97 21
        $subids = self::_decodeSubIDs(substr($data, $idx, $len));
98 20
        $idx += $len;
99
        // decode first subidentifier according to spec section 8.19.4
100 20
        if (isset($subids[0])) {
101 19
            if ($subids[0] < 80) {
102 13
                [$x, $y] = gmp_div_qr($subids[0], '40');
103
            } else {
104 6
                $x = gmp_init(2, 10);
105 6
                $y = $subids[0] - 80;
106
            }
107 19
            array_splice($subids, 0, 1, [$x, $y]);
108
        }
109 20
        $offset = $idx;
110 20
        return new self(self::_implodeSubIDs(...$subids));
111
    }
112
113
    /**
114
     * Explode dotted OID to an array of sub ID's.
115
     *
116
     * @param string $oid OID in dotted format
117
     *
118
     * @return \GMP[] Array of GMP numbers
119
     */
120 33
    protected static function _explodeDottedOID(string $oid): array
121
    {
122 33
        $subids = [];
123 33
        if (strlen($oid)) {
124 31
            foreach (explode('.', $oid) as $subid) {
125 31
                $n = @gmp_init($subid, 10);
126 31
                if (false === $n) {
127 1
                    throw new \UnexpectedValueException(
128 1
                        "'{$subid}' is not a number.");
129
                }
130 31
                $subids[] = $n;
131
            }
132
        }
133 32
        return $subids;
134
    }
135
136
    /**
137
     * Implode an array of sub IDs to dotted OID format.
138
     *
139
     * @param \GMP ...$subids
140
     */
141 22
    protected static function _implodeSubIDs(\GMP ...$subids): string
142
    {
143 22
        return implode('.',
144
            array_map(function ($num) {
145 21
                return gmp_strval($num, 10);
146 22
            }, $subids));
147
    }
148
149
    /**
150
     * Encode sub ID's to DER.
151
     *
152
     * @param \GMP ...$subids
153
     */
154 16
    protected static function _encodeSubIDs(\GMP ...$subids): string
155
    {
156 16
        $data = '';
157 16
        foreach ($subids as $subid) {
158
            // if number fits to one base 128 byte
159 15
            if ($subid < 128) {
160 14
                $data .= chr(intval($subid));
161
            } else { // encode to multiple bytes
162 4
                $bytes = [];
163
                do {
164 4
                    array_unshift($bytes, 0x7f & gmp_intval($subid));
165 4
                    $subid >>= 7;
166 4
                } while ($subid > 0);
167
                // all bytes except last must have bit 8 set to one
168 4
                foreach (array_splice($bytes, 0, -1) as $byte) {
169 4
                    $data .= chr(0x80 | $byte);
170
                }
171 15
                $data .= chr(reset($bytes));
172
            }
173
        }
174 16
        return $data;
175
    }
176
177
    /**
178
     * Decode sub ID's from DER data.
179
     *
180
     * @throws DecodeException
181
     *
182
     * @return \GMP[] Array of GMP numbers
183
     */
184 23
    protected static function _decodeSubIDs(string $data): array
185
    {
186 23
        $subids = [];
187 23
        $idx = 0;
188 23
        $end = strlen($data);
189 23
        while ($idx < $end) {
190 22
            $num = gmp_init('0', 10);
191 22
            while (true) {
192 22
                if ($idx >= $end) {
193 1
                    throw new DecodeException('Unexpected end of data.');
194
                }
195 22
                $byte = ord($data[$idx++]);
196 22
                $num |= $byte & 0x7f;
197
                // bit 8 of the last octet is zero
198 22
                if (!($byte & 0x80)) {
199 21
                    break;
200
                }
201 6
                $num <<= 7;
202
            }
203 21
            $subids[] = $num;
204
        }
205 22
        return $subids;
206
    }
207
}
208