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
![]() |
|||||||
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
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
![]() 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
![]() |
|||||||
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 |