Completed
Pull Request — master (#318)
by thomas
72:01
created

PrivateKey   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 95.16%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 178
ccs 59
cts 62
cp 0.9516
rs 10
wmc 15
lcom 1
cbo 11

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 3
A getPoint() 0 4 1
A getSecret() 0 4 1
A createExchange() 0 7 1
A sign() 0 4 1
A tweakAdd() 0 18 1
A tweakMul() 0 18 1
A isCompressed() 0 4 1
A getPublicKey() 0 14 2
A toWif() 0 10 2
A getBuffer() 0 4 1
1
<?php
2
3
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key;
4
5
use BitWasp\Bitcoin\Bitcoin;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Adapter\EcAdapter;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Serializer\Key\PrivateKeySerializer;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\Key;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PrivateKeyInterface;
10
use BitWasp\Bitcoin\Crypto\Random\RbgInterface;
11
use BitWasp\Bitcoin\Exceptions\InvalidPrivateKey;
12
use BitWasp\Bitcoin\Network\NetworkInterface;
13
use BitWasp\Bitcoin\Serializer\Key\PrivateKey\WifPrivateKeySerializer;
14
use BitWasp\Buffertools\Buffer;
15
use BitWasp\Buffertools\BufferInterface;
16
use Mdanter\Ecc\Crypto\EcDH\EcDH;
17
18
class PrivateKey extends Key implements PrivateKeyInterface, \Mdanter\Ecc\Crypto\Key\PrivateKeyInterface
19
{
20
    /**
21
     * @var \GMP
22
     */
23
    private $secretMultiplier;
24
25
    /**
26
     * @var bool
27
     */
28
    private $compressed;
29
30
    /**
31
     * @var PublicKey
32
     */
33
    private $publicKey;
34
35
    /**
36
     * @var EcAdapter
37
     */
38
    private $ecAdapter;
39
40
    /**
41
     * @param EcAdapter $ecAdapter
42
     * @param \GMP $int
43
     * @param bool $compressed
44
     * @throws InvalidPrivateKey
45 125
     */
46
    public function __construct(EcAdapter $ecAdapter, \GMP $int, $compressed = false)
47 125
    {
48 2
        if (false === $ecAdapter->validatePrivateKey(Buffer::int(gmp_strval($int, 10), 32, $ecAdapter->getMath()))) {
49
            throw new InvalidPrivateKey('Invalid private key - must be less than curve order.');
50
        }
51 123
52
        if (false === is_bool($compressed)) {
53
            throw new \InvalidArgumentException('PrivateKey: Compressed argument must be a boolean');
54
        }
55 123
        
56 123
        $this->ecAdapter = $ecAdapter;
57 123
        $this->secretMultiplier = $int;
58 123
        $this->compressed = $compressed;
59
    }
60
61
    /**
62
     * @return \Mdanter\Ecc\Primitives\GeneratorPoint
63 112
     */
64
    public function getPoint()
65 112
    {
66
        return $this->ecAdapter->getGenerator();
67
    }
68
69
    /**
70
     * @return \GMP
71
     */
72
    public function getSecret()
73
    {
74
        return $this->secretMultiplier;
75
    }
76
77
    /**
78
     * @param \Mdanter\Ecc\Crypto\Key\PublicKeyInterface $recipient
79
     * @return EcDH
80
     */
81
    public function createExchange(\Mdanter\Ecc\Crypto\Key\PublicKeyInterface $recipient)
82 14
    {
83
        $ecdh = new EcDH($this->ecAdapter->getMath());
84 14
        $ecdh->setSenderKey($this);
85 14
        $ecdh->setRecipientKey($recipient);
86
        return $ecdh;
87 14
    }
88 14
89
    /**
90 14
     * @param BufferInterface $msg32
91 14
     * @param RbgInterface|null $rbg
92 7
     * @return \BitWasp\Bitcoin\Crypto\EcAdapter\Signature\SignatureInterface
93 14
     */
94 7
    public function sign(BufferInterface $msg32, RbgInterface $rbg = null)
95 14
    {
96 7
        return $this->ecAdapter->sign($msg32, $this, $rbg);
97 14
    }
98 7
99
    /**
100
     * @param \GMP $tweak
101
     * @return PrivateKeyInterface
102
     */
103
    public function tweakAdd(\GMP $tweak)
104
    {
105 2
        $adapter = $this->ecAdapter;
106
        return $adapter->getPrivateKey(
107 2
            $adapter
108 2
                ->getMath()
109
                ->getModularArithmetic(
110 2
                    $adapter
111 2
                        ->getGenerator()
112
                        ->getOrder()
113 2
                )
114 2
                ->add(
115 1
                    $tweak,
116 2
                    $this->getSecret()
117 1
                ),
118 2
            $this->compressed
119 1
        );
120 2
    }
121 1
122
    /**
123
     * @param \GMP $tweak
124
     * @return PrivateKeyInterface
125
     */
126
    public function tweakMul(\GMP $tweak)
127 66
    {
128
        $adapter = $this->ecAdapter;
129 66
        return $adapter->getPrivateKey(
130
            $adapter
131
            ->getMath()
132
            ->getModularArithmetic(
133
                $adapter
134
                    ->getGenerator()
135
                    ->getOrder()
136
            )
137 129
            ->mul(
138
                $tweak,
139 129
                $this->getSecret()
140 105
            ),
141 105
            $this->compressed
142
        );
143 105
    }
144 105
145 105
    /**
146 53
     * {@inheritDoc}
147 53
     */
148
    public function isCompressed()
149 129
    {
150
        return $this->compressed;
151
    }
152
153
    /**
154
     * Return the public key
155
     *
156 6
     * @return PublicKey
157
     */
158 6
    public function getPublicKey()
159 6
    {
160 6
        if (null === $this->publicKey) {
161 6
            $adapter = $this->ecAdapter;
162 3
            $this->publicKey = $adapter->getPublicKey(
163
                $adapter
164 6
                    ->getGenerator()
165
                    ->mul($this->secretMultiplier),
166
                $this->compressed
167
            );
168
        }
169
170 66
        return $this->publicKey;
171
    }
172 66
173
    /**
174
     * @param NetworkInterface $network
175
     * @return string
176
     */
177
    public function toWif(NetworkInterface $network = null)
178
    {
179
        $network = $network ?: Bitcoin::getNetwork();
180
        $serializer = new WifPrivateKeySerializer(
181
            $this->ecAdapter->getMath(),
182
            new PrivateKeySerializer($this->ecAdapter)
183
        );
184
185
        return $serializer->serialize($network, $this);
186
    }
187
188
    /**
189
     * @return \BitWasp\Buffertools\BufferInterface
190
     */
191
    public function getBuffer()
192
    {
193
        return (new PrivateKeySerializer($this->ecAdapter))->serialize($this);
194
    }
195
}
196