Completed
Pull Request — master (#446)
by thomas
178:21 queued 108:18
created

PublicKey::getBuffer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Key;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Adapter\EcAdapter;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Serializer\Key\PublicKeySerializer;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\Key;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Signature\SignatureInterface;
10
use BitWasp\Buffertools\Buffer;
11
use BitWasp\Buffertools\BufferInterface;
12
13
class PublicKey extends Key implements PublicKeyInterface
14
{
15
    /**
16
     * @var EcAdapter
17
     */
18
    private $ecAdapter;
19
20
    /**
21
     * @var bool|false
22
     */
23
    private $compressed;
24
25
    /**
26
     * @var resource
27
     */
28
    private $pubkey_t;
29
30
    /**
31
     * @param EcAdapter $ecAdapter
32
     * @param resource $secp256k1_pubkey_t
33
     * @param bool|false $compressed
34
     */
35 520
    public function __construct(EcAdapter $ecAdapter, $secp256k1_pubkey_t, $compressed = false)
36
    {
37 520
        if (!is_resource($secp256k1_pubkey_t) ||
38 520
            !get_resource_type($secp256k1_pubkey_t) === SECP256K1_TYPE_PUBKEY) {
39
            throw new \InvalidArgumentException('Secp256k1\Key\PublicKey expects ' . SECP256K1_TYPE_PUBKEY . ' resource');
40
        }
41
42 520
        if (false === is_bool($compressed)) {
43
            throw new \InvalidArgumentException('PublicKey: Compressed must be a boolean');
44
        }
45
46 520
        $this->ecAdapter = $ecAdapter;
47 520
        $this->pubkey_t = $secp256k1_pubkey_t;
48 520
        $this->compressed = $compressed;
49 520
    }
50
    
51
    /**
52
     * @param BufferInterface $msg32
53
     * @param SignatureInterface $signature
54
     * @return bool
55
     */
56
    public function verify(BufferInterface $msg32, SignatureInterface $signature)
57
    {
58
        return $this->ecAdapter->verify($msg32, $this, $signature);
59
    }
60
61
    /**
62
     * @param PublicKey $other
63
     * @return bool
64 476
     */
65
    private function doEquals(self $other)
66 476
    {
67
        $context = $this->ecAdapter->getContext();
68
        $pubA = '';
69
        $pubB = '';
70
        if (!(secp256k1_ec_pubkey_serialize($context, $pubA, $this->pubkey_t, $this->compressed) && secp256k1_ec_pubkey_serialize($context, $pubB, $other->pubkey_t, $this->compressed))) {
71
            throw new \RuntimeException('Unable to serialize public key during equals');
72 452
        }
73
74 452
        return hash_equals($pubA, $pubB);
75
    }
76
77
    /**
78
     * @param PublicKeyInterface $other
79
     * @return bool
80
     */
81 20
    public function equals(PublicKeyInterface $other)
82
    {
83 20
        /** @var self $other */
84 20
        return $this->doEquals($other);
0 ignored issues
show
Documentation introduced by
$other is of type object<BitWasp\Bitcoin\C...ecp256k1\Key\PublicKey>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
85 20
    }
86
87
    /**
88
     * @return bool|false
89
     */
90 20
    public function isCompressed()
91 20
    {
92
        return $this->compressed;
93
    }
94
95 20
    /**
96
     * @return resource
97
     */
98
    public function getResource()
99
    {
100
        return $this->pubkey_t;
101
    }
102
103 16
    /**
104
     * @return resource
105 16
     * @throws \Exception
106 16
     */
107
    private function clonePubkey()
108 16
    {
109 16
        $context = $this->ecAdapter->getContext();
110
        $serialized = '';
111
        if (1 !== secp256k1_ec_pubkey_serialize($context, $serialized, $this->pubkey_t, $this->compressed)) {
112
            throw new \Exception('Secp256k1: pubkey serialize');
113 16
        }
114
115
        /** @var resource $clone */
116
        $clone = '';
117
        if (1 !== secp256k1_ec_pubkey_parse($context, $clone, $serialized)) {
118
            throw new \Exception('Secp256k1 pubkey parse');
119
        }
120
121 4
        return $clone;
122
    }
123 4
124 4
    /**
125
     * @param \GMP $tweak
126 4
     * @return PublicKey
127 4
     * @throws \Exception
128
     */
129
    public function tweakAdd(\GMP $tweak)
130
    {
131 4
        $context = $this->ecAdapter->getContext();
132
        $bin = Buffer::int(gmp_strval($tweak, 10), 32)->getBinary();
133
134
        $clone = $this->clonePubkey();
135
        if (1 !== secp256k1_ec_pubkey_tweak_add($context, $clone, $bin)) {
136
            throw new \RuntimeException('Secp256k1: tweak add failed.');
137 424
        }
138
139 424
        return new PublicKey($this->ecAdapter, $clone, $this->compressed);
140
    }
141
142
    /**
143
     * @param \GMP $tweak
144
     * @return PublicKey
145
     * @throws \Exception
146
     */
147
    public function tweakMul(\GMP $tweak)
148
    {
149
        $context = $this->ecAdapter->getContext();
150
        $bin = Buffer::int(gmp_strval($tweak, 10), 32)->getBinary();
151
152
        $clone = $this->clonePubkey();
153
        if (1 !== secp256k1_ec_pubkey_tweak_mul($context, $clone, $bin)) {
154
            throw new \RuntimeException('Secp256k1: tweak mul failed.');
155
        }
156
157
        return new PublicKey($this->ecAdapter, $clone, $this->compressed);
158
    }
159
160
    /**
161
     * @return BufferInterface
162
     */
163
    public function getBuffer()
164
    {
165
        return (new PublicKeySerializer($this->ecAdapter))->serialize($this);
166
    }
167
}
168