Completed
Pull Request — master (#591)
by thomas
22:54 queued 09:12
created

EcAdapter::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 2
nop 3
dl 0
loc 11
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Adapter;
6
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Key\PrivateKey;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Key\PublicKey;
10
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Signature\CompactSignature;
11
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PrivateKeyInterface;
12
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
13
use BitWasp\Bitcoin\Crypto\EcAdapter\Signature\CompactSignatureInterface;
14
use BitWasp\Bitcoin\Math\Math;
15
use BitWasp\Buffertools\BufferInterface;
16
use Mdanter\Ecc\Primitives\GeneratorPoint;
17
18
class EcAdapter implements EcAdapterInterface
19
{
20
    /**
21
     * @var Math
22
     */
23
    private $math;
24
25
    /**
26
     * @var \GMP
27
     */
28
    private $order;
29
30
    /**
31
     * @var GeneratorPoint
32
     */
33
    private $generator;
34
35
    /**
36
     * @var resource
37
     */
38
    private $context;
39
40
    /**
41
     * @param Math $math
42
     * @param GeneratorPoint $generator
43
     * @param resource $secp256k1_context_t
44
     */
45 2
    public function __construct(Math $math, GeneratorPoint $generator, $secp256k1_context_t)
46
    {
47 2
        if (!is_resource($secp256k1_context_t) || !get_resource_type($secp256k1_context_t) === SECP256K1_TYPE_CONTEXT) {
48
            throw new \InvalidArgumentException('Secp256k1: Must pass a secp256k1_context_t resource');
49
        }
50
51 2
        $this->math = $math;
52 2
        $this->generator = $generator;
53 2
        $this->order = $generator->getOrder();
54 2
        $this->context = $secp256k1_context_t;
55 2
    }
56
57
    /**
58
     * @return Math
59
     */
60 1294
    public function getMath(): Math
61
    {
62 1294
        return $this->math;
63
    }
64
65
    /**
66
     * @return \GMP
67
     */
68 7
    public function getOrder(): \GMP
69
    {
70 7
        return $this->order;
71
    }
72
73
    /**
74
     * @return GeneratorPoint
75
     */
76 5
    public function getGenerator()
77
    {
78 5
        return $this->generator;
79
    }
80
81
    /**
82
     * @param BufferInterface $privateKey
83
     * @return bool
84
     */
85 82
    public function validatePrivateKey(BufferInterface $privateKey): bool
86
    {
87 82
        return (bool) secp256k1_ec_seckey_verify($this->context, $privateKey->getBinary());
88
    }
89
90
    /**
91
     * @param \GMP $element
92
     * @param bool $half
93
     * @return bool
94
     */
95 4
    public function validateSignatureElement(\GMP $element, bool $half = false): bool
96
    {
97 4
        $math = $this->getMath();
98 4
        $against = $this->getOrder();
99 4
        if ($half) {
100 4
            $against = $math->rightShift($against, 1);
101
        }
102
103 4
        return $math->cmp($element, $against) < 0 && $math->cmp($element, gmp_init(0)) !== 0;
104
    }
105
106
    /**
107
     * @param \GMP $int
108
     * @param bool $compressed
109
     * @return PrivateKeyInterface
110
     */
111 76
    public function getPrivateKey(\GMP $int, bool $compressed = false): PrivateKeyInterface
112
    {
113 76
        return new PrivateKey($this, $int, $compressed);
114
    }
115
116
    /**
117
     * @return resource
118
     */
119 335
    public function getContext()
120
    {
121 335
        return $this->context;
122
    }
123
124
    /**
125
     * @param BufferInterface $msg32
126
     * @param CompactSignature $compactSig
127
     * @return PublicKey
128
     */
129 6
    private function doRecover(BufferInterface $msg32, CompactSignature $compactSig): PublicKey
130
    {
131 6
        $publicKey = '';
132
        /** @var resource $publicKey */
133 6
        $context = $this->context;
134 6
        $sig = $compactSig->getResource();
135 6
        if (1 !== secp256k1_ecdsa_recover($context, $publicKey, $sig, $msg32->getBinary())) {
136
            throw new \RuntimeException('Unable to recover Public Key');
137
        }
138
139 6
        return new PublicKey($this, $publicKey, $compactSig->isCompressed());
140
    }
141
142
    /**
143
     * @param BufferInterface $msg32
144
     * @param CompactSignatureInterface $compactSig
145
     * @return PublicKeyInterface
146
     */
147 6
    public function recover(BufferInterface $msg32, CompactSignatureInterface $compactSig): PublicKeyInterface
148
    {
149
        /** @var CompactSignature $compactSig */
150 6
        return $this->doRecover($msg32, $compactSig);
151
    }
152
}
153