Signer::verify()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 17
c 1
b 0
f 0
nc 3
nop 3
dl 0
loc 25
rs 9.3888
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Mdanter\Ecc\Crypto\Signature;
6
7
use Mdanter\Ecc\Math\GmpMathInterface;
8
use Mdanter\Ecc\Crypto\Key\PrivateKeyInterface;
9
use Mdanter\Ecc\Crypto\Key\PublicKeyInterface;
10
use Mdanter\Ecc\Util\BinaryString;
11
12
class Signer
13
{
14
15
    /**
16
     *
17
     * @var GmpMathInterface
18
     */
19
    private $adapter;
20
21
    /**
22
     *
23
     * @param GmpMathInterface $adapter
24
     */
25
    public function __construct(GmpMathInterface $adapter)
26
    {
27
        $this->adapter = $adapter;
28
    }
29
30
    /**
31
     * @param PrivateKeyInterface $key
32
     * @param \GMP $truncatedHash - hash truncated for use in ECDSA
33
     * @param \GMP $randomK
34
     * @return SignatureInterface
35
     */
36
    public function sign(PrivateKeyInterface $key, \GMP $truncatedHash, \GMP $randomK): SignatureInterface
37
    {
38
        $math = $this->adapter;
39
        $generator = $key->getPoint();
40
        $modMath = $math->getModularArithmetic($generator->getOrder());
41
42
        $k = $math->mod($randomK, $generator->getOrder());
43
        $p1 = $generator->mul($k);
44
        $r = $p1->getX();
45
        $zero = gmp_init(0, 10);
46
        if ($math->equals($r, $zero)) {
0 ignored issues
show
Bug introduced by
It seems like $zero can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMathInterface::equals() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

46
        if ($math->equals($r, /** @scrutinizer ignore-type */ $zero)) {
Loading history...
47
            throw new \RuntimeException("Error: random number R = 0");
48
        }
49
50
        $s = $modMath->div($modMath->add($truncatedHash, $math->mul($key->getSecret(), $r)), $k);
51
        if ($math->equals($s, $zero)) {
52
            throw new \RuntimeException("Error: random number S = 0");
53
        }
54
55
        return new Signature($r, $s);
56
    }
57
58
    /**
59
     * @param PublicKeyInterface $key
60
     * @param SignatureInterface $signature
61
     * @param \GMP $hash
62
     * @return bool
63
     */
64
    public function verify(PublicKeyInterface $key, SignatureInterface $signature, \GMP $hash): bool
65
    {
66
        $generator = $key->getGenerator();
67
        $n = $generator->getOrder();
68
        $r = $signature->getR();
69
        $s = $signature->getS();
70
71
        $math = $this->adapter;
72
        $one = gmp_init(1, 10);
73
        if ($math->cmp($r, $one) < 0 || $math->cmp($r, $math->sub($n, $one)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $one can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMathInterface::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
        if ($math->cmp($r, /** @scrutinizer ignore-type */ $one) < 0 || $math->cmp($r, $math->sub($n, $one)) > 0) {
Loading history...
Bug introduced by
It seems like $one can also be of type resource; however, parameter $subtrahend of Mdanter\Ecc\Math\GmpMathInterface::sub() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
        if ($math->cmp($r, $one) < 0 || $math->cmp($r, $math->sub($n, /** @scrutinizer ignore-type */ $one)) > 0) {
Loading history...
74
            return false;
75
        }
76
77
        if ($math->cmp($s, $one) < 0 || $math->cmp($s, $math->sub($n, $one)) > 0) {
78
            return false;
79
        }
80
81
        $modMath = $math->getModularArithmetic($n);
82
        $c = $math->inverseMod($s, $n);
83
        $u1 = $modMath->mul($hash, $c);
84
        $u2 = $modMath->mul($r, $c);
85
        $xy = $generator->mul($u1)->add($key->getPoint()->mul($u2));
86
        $v = $math->mod($xy->getX(), $n);
87
88
        return BinaryString::constantTimeCompare($math->toString($v), $math->toString($r));
89
    }
90
}
91