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

ObjectIdentifier   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 79
dl 0
loc 196
ccs 79
cts 79
cp 1
rs 10
c 0
b 0
f 0
wmc 27

8 Methods

Rating   Name   Duplication   Size   Complexity  
A oid() 0 3 1
A _encodeSubIDs() 0 21 5
A _implodeSubIDs() 0 6 1
A __construct() 0 23 6
A _decodeSubIDs() 0 22 5
A _encodedContentDER() 0 9 2
A _explodeDottedOID() 0 14 4
A _decodeFromDER() 0 19 3
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
     * @return string
71
     */
72 19
    public function oid(): string
73
    {
74 19
        return $this->_oid;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80 13
    protected function _encodedContentDER(): string
81
    {
82 13
        $subids = $this->_subids;
83
        // encode first two subids to one according to spec section 8.19.4
84 13
        if (count($subids) >= 2) {
85 12
            $num = ($subids[0] * 40) + $subids[1];
86 12
            array_splice($subids, 0, 2, [$num]);
87
        }
88 13
        return self::_encodeSubIDs(...$subids);
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94 21
    protected static function _decodeFromDER(Identifier $identifier,
95
        string $data, int &$offset): ElementBase
96
    {
97 21
        $idx = $offset;
98 21
        $len = Length::expectFromDER($data, $idx)->intLength();
99 21
        $subids = self::_decodeSubIDs(substr($data, $idx, $len));
100 20
        $idx += $len;
101
        // decode first subidentifier according to spec section 8.19.4
102 20
        if (isset($subids[0])) {
103 19
            if ($subids[0] < 80) {
104 13
                [$x, $y] = gmp_div_qr($subids[0], '40');
105
            } else {
106 6
                $x = gmp_init(2, 10);
107 6
                $y = $subids[0] - 80;
108
            }
109 19
            array_splice($subids, 0, 1, [$x, $y]);
110
        }
111 20
        $offset = $idx;
112 20
        return new self(self::_implodeSubIDs(...$subids));
113
    }
114
115
    /**
116
     * Explode dotted OID to an array of sub ID's.
117
     *
118
     * @param string $oid OID in dotted format
119
     *
120
     * @return \GMP[] Array of GMP numbers
121
     */
122 33
    protected static function _explodeDottedOID(string $oid): array
123
    {
124 33
        $subids = [];
125 33
        if (strlen($oid)) {
126 31
            foreach (explode('.', $oid) as $subid) {
127 31
                $n = @gmp_init($subid, 10);
128 31
                if (false === $n) {
129 1
                    throw new \UnexpectedValueException(
130 1
                        "'{$subid}' is not a number.");
131
                }
132 31
                $subids[] = $n;
133
            }
134
        }
135 32
        return $subids;
136
    }
137
138
    /**
139
     * Implode an array of sub IDs to dotted OID format.
140
     *
141
     * @param \GMP ...$subids
142
     *
143
     * @return string
144
     */
145 22
    protected static function _implodeSubIDs(\GMP ...$subids): string
146
    {
147 22
        return implode('.',
148
            array_map(function ($num) {
149 21
                return gmp_strval($num, 10);
150 22
            }, $subids));
151
    }
152
153
    /**
154
     * Encode sub ID's to DER.
155
     *
156
     * @param \GMP ...$subids
157
     *
158
     * @return string
159
     */
160 16
    protected static function _encodeSubIDs(\GMP ...$subids): string
161
    {
162 16
        $data = '';
163 16
        foreach ($subids as $subid) {
164
            // if number fits to one base 128 byte
165 15
            if ($subid < 128) {
166 14
                $data .= chr(intval($subid));
167
            } else { // encode to multiple bytes
168 4
                $bytes = [];
169
                do {
170 4
                    array_unshift($bytes, 0x7f & gmp_intval($subid));
171 4
                    $subid >>= 7;
172 4
                } while ($subid > 0);
173
                // all bytes except last must have bit 8 set to one
174 4
                foreach (array_splice($bytes, 0, -1) as $byte) {
175 4
                    $data .= chr(0x80 | $byte);
176
                }
177 15
                $data .= chr(reset($bytes));
178
            }
179
        }
180 16
        return $data;
181
    }
182
183
    /**
184
     * Decode sub ID's from DER data.
185
     *
186
     * @param string $data
187
     *
188
     * @throws DecodeException
189
     *
190
     * @return \GMP[] Array of GMP numbers
191
     */
192 23
    protected static function _decodeSubIDs(string $data): array
193
    {
194 23
        $subids = [];
195 23
        $idx = 0;
196 23
        $end = strlen($data);
197 23
        while ($idx < $end) {
198 22
            $num = gmp_init('0', 10);
199 22
            while (true) {
200 22
                if ($idx >= $end) {
201 1
                    throw new DecodeException('Unexpected end of data.');
202
                }
203 22
                $byte = ord($data[$idx++]);
204 22
                $num |= $byte & 0x7f;
205
                // bit 8 of the last octet is zero
206 22
                if (!($byte & 0x80)) {
207 21
                    break;
208
                }
209 6
                $num <<= 7;
210
            }
211 21
            $subids[] = $num;
212
        }
213 22
        return $subids;
214
    }
215
}
216