IssuerSerial::serial()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
nc 1
cc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace X509\AttributeCertificate;
6
7
use ASN1\Element;
8
use ASN1\Type\Constructed\Sequence;
9
use ASN1\Type\Primitive\Integer;
10
use X509\Certificate\Certificate;
11
use X509\Certificate\UniqueIdentifier;
12
use X509\GeneralName\DirectoryName;
13
use X509\GeneralName\GeneralNames;
14
15
/**
16
 * Implements <i>IssuerSerial</i> ASN.1 type.
17
 *
18
 * @link https://tools.ietf.org/html/rfc5755#section-4.1
19
 */
20
class IssuerSerial
21
{
22
    /**
23
     * Issuer name.
24
     *
25
     * @var GeneralNames $_issuer
26
     */
27
    protected $_issuer;
28
    
29
    /**
30
     * Serial number.
31
     *
32
     * @var string $_serial
33
     */
34
    protected $_serial;
35
    
36
    /**
37
     * Issuer unique ID.
38
     *
39
     * @var UniqueIdentifier|null $_issuerUID
40
     */
41
    protected $_issuerUID;
42
    
43
    /**
44
     * Constructor.
45
     *
46
     * @param GeneralNames $issuer
47
     * @param string|int $serial
48
     * @param UniqueIdentifier|null $uid
49
     */
50 19
    public function __construct(GeneralNames $issuer, $serial,
51
        UniqueIdentifier $uid = null)
52
    {
53 19
        $this->_issuer = $issuer;
54 19
        $this->_serial = strval($serial);
55 19
        $this->_issuerUID = $uid;
56 19
    }
57
    
58
    /**
59
     * Initialize from ASN.1.
60
     *
61
     * @param Sequence $seq
62
     * @return self
63
     */
64 9
    public static function fromASN1(Sequence $seq): IssuerSerial
65
    {
66 9
        $issuer = GeneralNames::fromASN1($seq->at(0)->asSequence());
67 9
        $serial = $seq->at(1)
68 9
            ->asInteger()
69 9
            ->number();
70 9
        $uid = null;
71 9
        if ($seq->has(2, Element::TYPE_BIT_STRING)) {
72 1
            $uid = UniqueIdentifier::fromASN1($seq->at(2)->asBitString());
73
        }
74 9
        return new self($issuer, $serial, $uid);
75
    }
76
    
77
    /**
78
     * Initialize from a public key certificate.
79
     *
80
     * @param Certificate $cert
81
     * @return self
82
     */
83 3
    public static function fromPKC(Certificate $cert): IssuerSerial
84
    {
85 3
        $tbsCert = $cert->tbsCertificate();
86 3
        $issuer = new GeneralNames(new DirectoryName($tbsCert->issuer()));
87 3
        $serial = $tbsCert->serialNumber();
88 3
        $uid = $tbsCert->hasIssuerUniqueID() ? $tbsCert->issuerUniqueID() : null;
89 3
        return new self($issuer, $serial, $uid);
90
    }
91
    
92
    /**
93
     * Get issuer name.
94
     *
95
     * @return GeneralNames
96
     */
97 2
    public function issuer(): GeneralNames
98
    {
99 2
        return $this->_issuer;
100
    }
101
    
102
    /**
103
     * Get serial number.
104
     *
105
     * @return string
106
     */
107 2
    public function serial(): string
108
    {
109 2
        return $this->_serial;
110
    }
111
    
112
    /**
113
     * Check whether issuer unique identifier is present.
114
     *
115
     * @return bool
116
     */
117 2
    public function hasIssuerUID(): bool
118
    {
119 2
        return isset($this->_issuerUID);
120
    }
121
    
122
    /**
123
     * Get issuer unique identifier.
124
     *
125
     * @throws \LogicException
126
     * @return UniqueIdentifier
127
     */
128 2
    public function issuerUID(): UniqueIdentifier
129
    {
130 2
        if (!$this->hasIssuerUID()) {
131 1
            throw new \LogicException("issuerUID not set.");
132
        }
133 1
        return $this->_issuerUID;
134
    }
135
    
136
    /**
137
     * Generate ASN.1 structure.
138
     *
139
     * @return Sequence
140
     */
141 23
    public function toASN1(): Sequence
142
    {
143 23
        $elements = array($this->_issuer->toASN1(), new Integer($this->_serial));
144 23
        if (isset($this->_issuerUID)) {
145 1
            $elements[] = $this->_issuerUID->toASN1();
146
        }
147 23
        return new Sequence(...$elements);
148
    }
149
    
150
    /**
151
     * Check whether this IssuerSerial identifies given certificate.
152
     *
153
     * @param Certificate $cert
154
     * @return boolean
155
     */
156 19
    public function identifiesPKC(Certificate $cert): bool
157
    {
158 19
        $tbs = $cert->tbsCertificate();
159 19
        if (!$tbs->issuer()->equals($this->_issuer->firstDN())) {
160 3
            return false;
161
        }
162 16
        if (strval($tbs->serialNumber()) != strval($this->_serial)) {
163 1
            return false;
164
        }
165 15
        if ($this->_issuerUID && !$this->_checkUniqueID($cert)) {
166 2
            return false;
167
        }
168 13
        return true;
169
    }
170
    
171
    /**
172
     * Check whether issuerUID matches given certificate.
173
     *
174
     * @param Certificate $cert
175
     * @return boolean
176
     */
177 3
    private function _checkUniqueID(Certificate $cert): bool
178
    {
179 3
        if (!$cert->tbsCertificate()->hasIssuerUniqueID()) {
180 1
            return false;
181
        }
182 2
        $uid = $cert->tbsCertificate()
183 2
            ->issuerUniqueID()
184 2
            ->string();
185 2
        if ($this->_issuerUID->string() != $uid) {
186 1
            return false;
187
        }
188 1
        return true;
189
    }
190
}
191