Passed
Push — master ( 2515b7...d118c3 )
by Thomas
02:22
created

CoseKey::asPem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace MadWizard\WebAuthn\Crypto;
4
5
use MadWizard\WebAuthn\Exception\DataValidationException;
6
use MadWizard\WebAuthn\Exception\WebAuthnException;
7
use MadWizard\WebAuthn\Format\ByteBuffer;
8
use MadWizard\WebAuthn\Format\CborDecoder;
9
use MadWizard\WebAuthn\Format\CborMap;
10
use MadWizard\WebAuthn\Format\DataValidator;
11
12
abstract class CoseKey implements CoseKeyInterface
13
{
14
    /**
15
     * OKP key type.
16
     */
17
    protected const COSE_KTY_OKP = 1;
18
19
    /**
20
     * EC2 key type.
21
     */
22
    protected const COSE_KTY_EC2 = 2;
23
24
    /**
25
     * RSA key type.
26
     */
27
    protected const COSE_KTY_RSA = 3;
28
29
    /**
30
     * @var int
31
     */
32
    private $algorithm;
33
34
    /**
35
     * Identification of the key type.
36
     *
37
     * @see https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters
38
     */
39
    protected const COSE_KEY_PARAM_KTY = 1;
40
41
    /**
42
     * Key identification value.
43
     *
44
     * @see https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters
45
     */
46
    protected const COSE_KEY_PARAM_KID = 2;
47
48
    /**
49
     * Key usage restriction to this algorithm.
50
     *
51
     * @see https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters
52
     */
53
    protected const COSE_KEY_PARAM_ALG = 3;
54
55
    /**
56
     * CoseKey constructor.
57
     *
58
     * @param int $algorithm IANA COSE Algorithm
59
     *
60
     * @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
61
     */
62 49
    public function __construct(int $algorithm)
63
    {
64 49
        if (!$this->algorithmSupported($algorithm)) {
65
            throw new WebAuthnException('Algorithm not supported');
66
        }
67 49
        $this->algorithm = $algorithm;
68 49
    }
69
70
    public function toString(): string
71
    {
72
        return $this->getCbor()->getBase64Url();
73
    }
74
75 20
    public static function parseCbor(ByteBuffer $buffer, int $offset = 0, int &$endOffset = null): CoseKey
76
    {
77 20
        $data = CborDecoder::decodeInPlace($buffer, $offset, $endOffset);
78
79 20
        if (!$data instanceof CborMap) {
80
            throw new DataValidationException('Failed to decode CBOR encoded COSE key'); // TODO: change exceptions
81
        }
82
83 20
        DataValidator::checkMap(
84 20
            $data,
85
            [
86 20
                self::COSE_KEY_PARAM_KTY => 'integer',
87
            ],
88 20
            false
89
        );
90
91 20
        $keyType = $data->get(self::COSE_KEY_PARAM_KTY);
92 20
        return self::createKey($keyType, $data);
93
    }
94
95 5
    public static function fromString(string $key): CoseKey
96
    {
97 5
        return self::parseCbor(ByteBuffer::fromBase64Url($key));
98
    }
99
100 20
    private static function createKey(int $keyType, CborMap $data): CoseKey
101
    {
102 20
        if ($keyType === self::COSE_KTY_EC2) {
103 16
            return Ec2Key::fromCborData($data);
104
        }
105 4
        if ($keyType === self::COSE_KTY_OKP) {
106 1
            return OkpKey::fromCborData($data);
107
        }
108 3
        if ($keyType === self::COSE_KTY_RSA) {
109 3
            return RsaKey::fromCborData($data);
110
        }
111
        throw new WebAuthnException(sprintf('Key type %d not supported', $keyType));
112
    }
113
114
    abstract public function getCbor(): ByteBuffer;
115
116 19
    public function getAlgorithm(): int
117
    {
118 19
        return $this->algorithm;
119
    }
120
121
    abstract public function verifySignature(ByteBuffer $data, ByteBuffer $signature): bool;
122
123
    abstract protected function algorithmSupported(int $algorithm): bool;
124
125
    abstract public function asDer(): string;
126
127 15
    public function asPem(): string
128
    {
129 15
        return Der::pem('PUBLIC KEY', $this->asDer());
130
    }
131
}
132