Passed
Branch master (8940db)
by Sam
02:38
created

CERT::getKeyTag()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Badcow DNS Library.
7
 *
8
 * (c) Samuel Williams <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Badcow\DNS\Rdata;
15
16
/*
17
 * {@link https://tools.ietf.org/html/rfc4398#section-2.1}.
18
 */
19
use Badcow\DNS\Parser\Tokens;
20
21
class CERT implements RdataInterface
22
{
23
    use RdataTrait;
24
25
    const TYPE = 'CERT';
26
    const TYPE_CODE = 37;
27
28
    const KEY_TYPE_PKIX = 1;
29
    const KEY_TYPE_SPKI = 2;
30
    const KEY_TYPE_PGP = 3;
31
    const KEY_TYPE_IPKIX = 4;
32
    const KEY_TYPE_ISPKI = 5;
33
    const KEY_TYPE_IPGP = 6;
34
    const KEY_TYPE_ACPKIX = 7;
35
    const KEY_TYPE_IACPKIX = 8;
36
    const KEY_TYPE_URI = 253;
37
    const KEY_TYPE_OID = 254;
38
39
    const MNEMONICS = [
40
        self::KEY_TYPE_PKIX => 'PKIX',
41
        self::KEY_TYPE_SPKI => 'SPKI',
42
        self::KEY_TYPE_PGP => 'PGP',
43
        self::KEY_TYPE_IPKIX => 'IPKIX',
44
        self::KEY_TYPE_ISPKI => 'ISPKI',
45
        self::KEY_TYPE_IPGP => 'IPGP',
46
        self::KEY_TYPE_ACPKIX => 'ACPKIX',
47
        self::KEY_TYPE_IACPKIX => 'IACPKIX',
48
        self::KEY_TYPE_URI => 'URI',
49
        self::KEY_TYPE_OID => 'OID',
50
    ];
51
52
    /**
53
     * @var int
54
     */
55
    private $certificateType;
56
57
    /**
58
     * @var int
59
     */
60
    private $keyTag;
61
62
    /**
63
     * @var int
64
     */
65
    private $algorithm;
66
67
    /**
68
     * @var string
69
     */
70
    private $certificate;
71
72
    /**
73
     * @return int
74
     */
75
    public function getCertificateType(): int
76
    {
77
        return $this->certificateType;
78
    }
79
80
    /**
81
     * @param int|string $certificateType
82
     *
83
     * @throws \InvalidArgumentException
84
     */
85 4
    public function setCertificateType($certificateType): void
86
    {
87 4
        if (is_int($certificateType) || 1 === preg_match('/^\d+$/', $certificateType)) {
88 1
            $this->certificateType = (int) $certificateType;
89
90 1
            return;
91
        }
92
93 4
        $this->certificateType = self::getKeyTypeValue((string) $certificateType);
94 4
    }
95
96
    /**
97
     * @return int
98
     */
99
    public function getKeyTag(): int
100
    {
101
        return $this->keyTag;
102
    }
103
104
    /**
105
     * @param int $keyTag
106
     */
107 4
    public function setKeyTag(int $keyTag): void
108
    {
109 4
        $this->keyTag = $keyTag;
110 4
    }
111
112
    /**
113
     * @return int
114
     */
115
    public function getAlgorithm(): int
116
    {
117
        return $this->algorithm;
118
    }
119
120
    /**
121
     * @param string|int $algorithm
122
     *
123
     * @throws \InvalidArgumentException
124
     */
125 4
    public function setAlgorithm($algorithm): void
126
    {
127 4
        if (is_int($algorithm) || 1 === preg_match('/^\d+$/', $algorithm)) {
128 4
            $this->algorithm = (int) $algorithm;
129
130 4
            return;
131
        }
132
133 1
        $this->algorithm = Algorithms::getAlgorithmValue((string) $algorithm);
134 1
    }
135
136
    /**
137
     * @param string $certificate Base64 encoded string
138
     *
139
     * @throws \InvalidArgumentException
140
     */
141 4
    public function setCertificate(string $certificate): void
142
    {
143 4
        if (false === $decoded = base64_decode($certificate)) {
144
            throw new \InvalidArgumentException('The certificate must be a valid Base64 encoded string.');
145
        }
146
147 4
        $this->certificate = $decoded;
148 4
    }
149
150
    /**
151
     * @return string Base64 encoded string
152
     */
153 1
    public function getCertificate(): string
154
    {
155 1
        return base64_encode($this->certificate);
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 1
    public function toText(): string
162
    {
163 1
        $type = (array_key_exists($this->certificateType, self::MNEMONICS)) ? self::MNEMONICS[$this->certificateType] : (string) $this->certificateType;
164 1
        $algorithm = (array_key_exists($this->algorithm, Algorithms::MNEMONICS)) ? Algorithms::MNEMONICS[$this->algorithm] : (string) $this->algorithm;
165
166 1
        return sprintf('%s %s %s %s', $type, (string) $this->keyTag, $algorithm, $this->getCertificate());
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172 1
    public function toWire(): string
173
    {
174 1
        return pack('nnC', $this->certificateType, $this->keyTag, $this->algorithm).$this->certificate;
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 1
    public static function fromText(string $text): RdataInterface
181
    {
182 1
        $rdata = explode(Tokens::SPACE, $text);
183 1
        $cert = new static();
184 1
        $cert->setCertificateType((string) array_shift($rdata));
185 1
        $cert->setKeyTag((int) array_shift($rdata));
186 1
        $cert->setAlgorithm((string) array_shift($rdata));
187 1
        $cert->setCertificate(implode('', $rdata));
188
189 1
        return $cert;
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195 1
    public static function fromWire(string $rdata): RdataInterface
196
    {
197 1
        $integers = unpack('ntype/nkeyTag/Calgorithm', $rdata);
198 1
        $cert = new static();
199 1
        $cert->setCertificateType((int) $integers['type']);
200 1
        $cert->setKeyTag((int) $integers['keyTag']);
201 1
        $cert->setAlgorithm((int) $integers['algorithm']);
202 1
        $cert->setCertificate(base64_encode(substr($rdata, 5)));
203
204 1
        return $cert;
205
    }
206
207
    /**
208
     * @param string $keyTypeMnemonic
209
     *
210
     * @return int
211
     *
212
     * @throws \InvalidArgumentException
213
     */
214 4
    public static function getKeyTypeValue(string $keyTypeMnemonic): int
215
    {
216 4
        if (false === $keyTypeValue = array_search($keyTypeMnemonic, self::MNEMONICS, true)) {
217
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid key type mnemonic.', $keyTypeMnemonic));
218
        }
219
220 4
        return (int) $keyTypeValue;
221
    }
222
223
    /**
224
     * Get the associated mnemonic of a key type.
225
     *
226
     * @param int $keyTypeValue
227
     *
228
     * @return string
229
     *
230
     * @throws \InvalidArgumentException
231
     */
232
    public static function getKeyTypeMnemonic(int $keyTypeValue): string
233
    {
234
        if (!array_key_exists($keyTypeValue, self::MNEMONICS)) {
235
            throw new \InvalidArgumentException(sprintf('"%d" is not a valid key type.', $keyTypeValue));
236
        }
237
238
        return self::MNEMONICS[$keyTypeValue];
239
    }
240
}
241