Completed
Pull Request — master (#403)
by thomas
75:49 queued 72:57
created

PrivateKey::createExchange()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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