Completed
Pull Request — master (#359)
by Ruben de
14:27
created

PrivateKey::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
nc 3
nop 3
dl 0
loc 14
ccs 8
cts 9
cp 0.8889
crap 3.0123
rs 9.4285
c 2
b 0
f 0
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
     */
46 64
    public function __construct(EcAdapter $ecAdapter, \GMP $int, $compressed = false)
47
    {
48 64
        if (false === $ecAdapter->validatePrivateKey(Buffer::int(gmp_strval($int, 10), 32, $ecAdapter->getMath()))) {
49 1
            throw new InvalidPrivateKey('Invalid private key - must be less than curve order.');
50
        }
51
52 63
        if (false === is_bool($compressed)) {
53
            throw new \InvalidArgumentException('PrivateKey: Compressed argument must be a boolean');
54
        }
55
        
56 63
        $this->ecAdapter = $ecAdapter;
57 63
        $this->secretMultiplier = $int;
58 63
        $this->compressed = $compressed;
59 63
    }
60
61
    /**
62
     * @return \Mdanter\Ecc\Primitives\GeneratorPoint
63
     */
64 23
    public function getPoint()
65
    {
66 23
        return $this->ecAdapter->getGenerator();
67
    }
68
69
    /**
70
     * @return \GMP
71
     */
72 56
    public function getSecret()
73
    {
74 56
        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
    {
83
        $ecdh = new EcDH($this->ecAdapter->getMath());
84
        $ecdh->setSenderKey($this);
85
        $ecdh->setRecipientKey($recipient);
86
        return $ecdh;
87
    }
88
89
    /**
90
     * @param BufferInterface $msg32
91
     * @param RbgInterface|null $rbg
92
     * @return \BitWasp\Bitcoin\Crypto\EcAdapter\Signature\SignatureInterface
93
     */
94
    public function sign(BufferInterface $msg32, RbgInterface $rbg = null)
95
    {
96
        return $this->ecAdapter->sign($msg32, $this, $rbg);
97
    }
98
99
    /**
100
     * @param \GMP $tweak
101
     * @return PrivateKeyInterface
102
     */
103 7
    public function tweakAdd(\GMP $tweak)
104
    {
105 7
        $adapter = $this->ecAdapter;
106 7
        return $adapter->getPrivateKey(
107
            $adapter
108 7
                ->getMath()
109 7
                ->getModularArithmetic(
110
                    $adapter
111 7
                        ->getGenerator()
112 7
                        ->getOrder()
113
                )
114 7
                ->add(
115
                    $tweak,
116 7
                    $this->getSecret()
117
                ),
118 7
            $this->compressed
119
        );
120
    }
121
122
    /**
123
     * @param \GMP $tweak
124
     * @return PrivateKeyInterface
125
     */
126 1
    public function tweakMul(\GMP $tweak)
127
    {
128 1
        $adapter = $this->ecAdapter;
129 1
        return $adapter->getPrivateKey(
130
            $adapter
131 1
            ->getMath()
132 1
            ->getModularArithmetic(
133
                $adapter
134 1
                    ->getGenerator()
135 1
                    ->getOrder()
136
            )
137 1
            ->mul(
138
                $tweak,
139 1
                $this->getSecret()
140
            ),
141 1
            $this->compressed
142
        );
143
    }
144
145
    /**
146
     * {@inheritDoc}
147
     */
148 33
    public function isCompressed()
149
    {
150 33
        return $this->compressed;
151
    }
152
153
    /**
154
     * Return the public key
155
     *
156
     * @return PublicKey
157
     */
158 66
    public function getPublicKey()
159
    {
160 66
        if (null === $this->publicKey) {
161 54
            $adapter = $this->ecAdapter;
162 54
            $this->publicKey = $adapter->getPublicKey(
163
                $adapter
164 54
                    ->getGenerator()
165 54
                    ->mul($this->secretMultiplier),
166 54
                $this->compressed
167 1
            );
168 1
        }
169
170 66
        return $this->publicKey;
171
    }
172
173
    /**
174
     * @param NetworkInterface $network
175
     * @return string
176
     */
177 3
    public function toWif(NetworkInterface $network = null)
178
    {
179 3
        $network = $network ?: Bitcoin::getNetwork();
180 3
        $serializer = new WifPrivateKeySerializer(
181 3
            $this->ecAdapter->getMath(),
182 3
            new PrivateKeySerializer($this->ecAdapter)
183
        );
184
185 3
        return $serializer->serialize($network, $this);
186
    }
187
188
    /**
189
     * @return \BitWasp\Buffertools\BufferInterface
190
     */
191 33
    public function getBuffer()
192
    {
193 33
        return (new PrivateKeySerializer($this->ecAdapter))->serialize($this);
194
    }
195
}
196