Completed
Push — master ( 7b61ef...71e756 )
by Florent
08:30 queued 07:08
created

EdDSA   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 66
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 1
dl 0
loc 66
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A allowedKeyTypes() 0 4 1
A sign() 0 17 3
A verify() 0 13 2
A name() 0 4 1
A checkKey() 0 14 5
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2019 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace Jose\Component\Signature\Algorithm;
15
16
use Base64Url\Base64Url;
17
use InvalidArgumentException;
18
use Jose\Component\Core\JWK;
19
use RuntimeException;
20
21
final class EdDSA implements SignatureAlgorithm
22
{
23
    public function __construct()
24
    {
25
        if (!\extension_loaded('sodium')) {
26
            throw new RuntimeException('The extension "sodium" is not available. Please install it to use this method');
27
        }
28
    }
29
30
    public function allowedKeyTypes(): array
31
    {
32
        return ['OKP'];
33
    }
34
35
    public function sign(JWK $key, string $input): string
36
    {
37
        $this->checkKey($key);
38
        if (!$key->has('d')) {
39
            throw new InvalidArgumentException('The EC key is not private');
40
        }
41
        $x = Base64Url::decode($key->get('x'));
42
        $d = Base64Url::decode($key->get('d'));
43
        $secret = $d.$x;
44
45
        switch ($key->get('crv')) {
46
            case 'Ed25519':
47
                return sodium_crypto_sign_detached($input, $secret);
48
            default:
49
                throw new InvalidArgumentException('Unsupported curve');
50
        }
51
    }
52
53
    public function verify(JWK $key, string $input, string $signature): bool
54
    {
55
        $this->checkKey($key);
56
57
        $public = Base64Url::decode($key->get('x'));
58
59
        switch ($key->get('crv')) {
60
            case 'Ed25519':
61
                return sodium_crypto_sign_verify_detached($signature, $input, $public);
62
            default:
63
                throw new InvalidArgumentException('Unsupported curve');
64
        }
65
    }
66
67
    public function name(): string
68
    {
69
        return 'EdDSA';
70
    }
71
72
    private function checkKey(JWK $key): void
73
    {
74
        if (!\in_array($key->get('kty'), $this->allowedKeyTypes(), true)) {
75
            throw new InvalidArgumentException('Wrong key type.');
76
        }
77
        foreach (['x', 'crv'] as $k) {
78
            if (!$key->has($k)) {
79
                throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k));
80
            }
81
        }
82
        if ('Ed25519' !== $key->get('crv')) {
83
            throw new InvalidArgumentException('Unsupported curve.');
84
        }
85
    }
86
}
87