Cryptokey::getTag()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 0
dl 0
loc 19
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the CwdPowerDNS Client
5
 *
6
 * (c) 2018 cwd.at GmbH <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cwd\PowerDNSClient\Model;
15
16
use Symfony\Component\Validator\Constraints as Assert;
17
use Symfony\Component\Validator\Context\ExecutionContextInterface;
18
19
class Cryptokey
20
{
21
    protected const VALID_KEYTYPES = [
22
        'ksk',
23
        'zsk',
24
        'csk',
25
    ];
26
27
    // https://doc.powerdns.com/md/authoritative/dnssec/#supported-algorithms
28
    // https://github.com/operasoftware/dns-ui/issues/57#issuecomment-377553394
29
    public const VALID_ALGORITHMS = [
30
        1 => 'RSAMD5',
31
        2 => 'DH',
32
        3 => 'DSA',
33
34
        5 => 'RSASHA1',
35
        6 => 'DSA-NSEC3-SHA1',
36
        7 => 'RSASHA1-NSEC3-SHA1',
37
        8 => 'RSASHA256',
38
39
        10 => 'RSASHA512',
40
41
        12 => 'ECC-GOST',
42
        13 => 'ECDSAP256SHA256',
43
        14 => 'ECDSAP384SHA384',
44
        15 => 'ED25519',
45
        16 => 'ED448',
46
    ];
47
48
    /** @var string */
49
    protected $type = 'Cryptokey';
50
51
    /** @var int */
52
    protected $id;
53
    /**
54
     * @var string
55
     * @Assert\Choice(
56
     *   choices = {"ksk", "zsk", "csk"},
57
     *   groups={"CREATE"}
58
     * )
59
     */
60
    protected $keytype;
61
62
    /** @var bool */
63
    protected $active = false;
64
    /** @var string */
65
    protected $dnskey;
66
    /** @var string[] */
67
    protected $ds = [];
68
    /** @var string */
69
    protected $protectedkey;
70
    /** @var string */
71
    protected $algorithm;
72
    /** @var int */
73
    protected $bits;
74
75
    /**
76
     * @return string
77
     */
78
    public function getType(): string
79
    {
80
        return $this->type;
81
    }
82
83
    /**
84
     * @param string $type
85
     *
86
     * @return Cryptokey
87
     */
88
    public function setType(string $type): Cryptokey
89
    {
90
        $this->type = $type;
91
92
        return $this;
93
    }
94
95
    /**
96
     * @return string
97
     */
98
    public function getId(): ?int
99
    {
100
        return $this->id;
101
    }
102
103
    /**
104
     * @param int $id
105
     *
106
     * @return Cryptokey
107
     */
108
    public function setId(int $id): Cryptokey
109
    {
110
        $this->id = $id;
111
112
        return $this;
113
    }
114
115
    /**
116
     * @return string
117
     */
118
    public function getKeytype(): ?string
119
    {
120
        return $this->keytype;
121
    }
122
123
    /**
124
     * @param string $keytype
125
     *
126
     * @return Cryptokey
127
     */
128
    public function setKeytype(string $keytype): Cryptokey
129
    {
130
        $this->keytype = $keytype;
131
132
        return $this;
133
    }
134
135
    /**
136
     * @return bool
137
     */
138
    public function isActive(): bool
139
    {
140
        return $this->active;
141
    }
142
143
    /**
144
     * @param bool $active
145
     *
146
     * @return Cryptokey
147
     */
148
    public function setActive(bool $active): Cryptokey
149
    {
150
        $this->active = $active;
151
152
        return $this;
153
    }
154
155
    /**
156
     * @return string
157
     */
158
    public function getDnskey(): ?string
159
    {
160
        return $this->dnskey;
161
    }
162
163
    /**
164
     * @param string $dnskey
165
     *
166
     * @return Cryptokey
167
     */
168
    public function setDnskey(string $dnskey): Cryptokey
169
    {
170
        $this->dnskey = $dnskey;
171
172
        return $this;
173
    }
174
175
    /**
176
     * @return string[]
177
     */
178
    public function getDs(): array
179
    {
180
        return $this->ds;
181
    }
182
183
    /**
184
     * @param string[] $ds
185
     *
186
     * @return Cryptokey
187
     */
188
    public function setDs(array $ds): Cryptokey
189
    {
190
        $this->ds = $ds;
191
192
        return $this;
193
    }
194
195
    /**
196
     * @return string
197
     */
198
    public function getprotectedkey(): ?string
199
    {
200
        return $this->protectedkey;
201
    }
202
203
    /**
204
     * @param string $protectedkey
205
     *
206
     * @return Cryptokey
207
     */
208
    public function setprotectedkey(string $protectedkey): Cryptokey
209
    {
210
        $this->protectedkey = $protectedkey;
211
212
        return $this;
213
    }
214
215
    /**
216
     * @return string|int|null
217
     */
218
    public function getAlgorithm()
219
    {
220
        return $this->algorithm;
221
    }
222
223
    /**
224
     * @param string|int $algorithm
225
     *
226
     * @return Cryptokey
227
     */
228
    public function setAlgorithm($algorithm): Cryptokey
229
    {
230
        $this->algorithm = $algorithm;
231
232
        return $this;
233
    }
234
235
    /**
236
     * @return int
237
     */
238
    public function getBits(): ?int
239
    {
240
        return $this->bits;
241
    }
242
243
    /**
244
     * @param int $bits
245
     *
246
     * @return Cryptokey
247
     */
248
    public function setBits(int $bits): Cryptokey
249
    {
250
        $this->bits = $bits;
251
252
        return $this;
253
    }
254
255
    /**
256
     * Reconstruct the DNSKEY RDATA wire format (https://tools.ietf.org/html/rfc4034#section-2.1)
257
     * by merging the flags, protocol, algorithm, and the base64-decoded key data
258
     * https://github.com/operasoftware/dns-ui/commit/35821799f7c2a2e17e9178612e24147dfe7c0867#diff-0d3376b053b1313ed26a84a0c61ef0f2R344
259
     * by Thomas Pike.
260
     *
261
     * @return string
262
     */
263
    public function getTag(): ?int
264
    {
265
        if (null === $this->dnskey) {
266
            return null;
267
        }
268
269
        list($flags, $protocol, $algorithm, $keydata) = preg_split('/\s+/', $this->dnskey);
270
271
        $wire_format = pack('nCC', $flags, $protocol, $algorithm).base64_decode($keydata);
272
        // Split data into (zero-indexed) array of bytes
273
        $keyvalues = array_values(unpack('C*', $wire_format));
274
        // Follow algorithm from RFC 4034 Appendix B (https://tools.ietf.org/html/rfc4034#appendix-B)
275
        $ac = 0;
276
        foreach ($keyvalues as $i => $keyvalue) {
277
            $ac += ($i & 1) ? $keyvalue : $keyvalue << 8;
278
        }
279
        $ac += ($ac >> 16) & 0xFFFF;
280
281
        return $ac & 0xFFFF;
282
    }
283
284
    /**
285
     * @param ExecutionContextInterface $context
286
     * @param $payload
287
     * @Assert\Callback(groups={"CREATE"})
288
     */
289
    public function validateAlgos(ExecutionContextInterface $context, $payload): void
290
    {
291
        if (null === $this->getAlgorithm()) {
292
            return;
293
        }
294
295
        if (\is_integer($this->getAlgorithm()) && !\array_key_exists($this->getAlgorithm(), self::VALID_ALGORITHMS)) {
296
            $context->buildViolation(sprintf('Algorithm "%s" is unknown', $this->getAlgorithm()))
297
                ->atPath('algorithm')
298
                ->addViolation();
299
        }
300
301
        if (\is_string($this->getAlgorithm()) && !\in_array($this->getAlgorithm(), self::VALID_ALGORITHMS, false)) {
302
            $context->buildViolation(sprintf('Algorithm "%s" is unknown', $this->getAlgorithm()))
303
                ->atPath('algorithm')
304
                ->addViolation();
305
        }
306
    }
307
}
308