Failed Conditions
Push — v7 ( 514019...c6ee27 )
by Florent
02:57
created

ECDSA   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 3
dl 0
loc 72
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A sign() 0 15 3
A verify() 0 12 2
getHashAlgorithm() 0 1 ?
getSignaturePartLength() 0 1 ?
A checkKey() 0 11 4
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2017 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 Jose\Component\Core\JWK;
17
use Jose\Component\Core\Util\ECSignature;
18
use Jose\Component\Core\Util\ECKey;
19
use Jose\Component\Signature\SignatureAlgorithmInterface;
20
21
/**
22
 * Class ECDSA.
23
 */
24
abstract class ECDSA implements SignatureAlgorithmInterface
25
{
26
    /**
27
     * ECDSA constructor.
28
     */
29
    public function __construct()
30
    {
31
        if (!defined('OPENSSL_KEYTYPE_EC')) {
32
            throw new \RuntimeException('Elliptic Curve key type not supported by your environment.');
33
        }
34
    }
35
36
    /**
37
     * {@inheritdoc}
38
     */
39
    public function sign(JWK $key, string $input): string
40
    {
41
        $this->checkKey($key);
42
        if (!$key->has('d')) {
43
            throw new \InvalidArgumentException('The EC key is not private');
44
        }
45
46
        $pem = ECKey::convertPrivateKeyToPEM($key);
47
        $result = openssl_sign($input, $signature, $pem, $this->getHashAlgorithm());
48
        if (false === $result) {
49
            throw new \RuntimeException('Signature failed.');
50
        }
51
52
        return ECSignature::fromDER($signature, $this->getSignaturePartLength());
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function verify(JWK $key, string $input, string $signature): bool
59
    {
60
        $this->checkKey($key);
61
        try {
62
            $der = ECSignature::toDER($signature, $this->getSignaturePartLength());
63
            $pem = ECKey::convertPublicKeyToPEM($key);
64
            return 1 === openssl_verify($input, $der, $pem, $this->getHashAlgorithm());
65
66
        } catch (\Exception $e) {
67
            return false;
68
        }
69
    }
70
71
    /**
72
     * @return string
73
     */
74
    abstract protected function getHashAlgorithm(): string;
75
76
    /**
77
     * @return int
78
     */
79
    abstract protected function getSignaturePartLength(): int;
80
81
    /**
82
     * @param JWK $key
83
     */
84
    private function checkKey(JWK $key)
85
    {
86
        if ('EC' !== $key->get('kty')) {
87
            throw new \InvalidArgumentException('Wrong key type.');
88
        }
89
        foreach (['x', 'y', 'crv'] as $k) {
90
            if (!$key->has($k)) {
91
                throw new \InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k));
92
            }
93
        }
94
    }
95
}
96