Completed
Pull Request — master (#446)
by thomas
105:00 queued 101:56
created

PublicKey::equals()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.125

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 2
cts 4
cp 0.5
crap 1.125
rs 9.4285
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 133
    public function __construct(EcAdapter $ecAdapter, $secp256k1_pubkey_t, $compressed = false)
36
    {
37 133
        if (!is_resource($secp256k1_pubkey_t) ||
38 133
            !get_resource_type($secp256k1_pubkey_t) === SECP256K1_TYPE_PUBKEY) {
39
            throw new \InvalidArgumentException('Secp256k1\Key\PublicKey expects ' . SECP256K1_TYPE_PUBKEY . ' resource');
40
        }
41
42 133
        if (false === is_bool($compressed)) {
43
            throw new \InvalidArgumentException('PublicKey: Compressed must be a boolean');
44
        }
45
46 133
        $this->ecAdapter = $ecAdapter;
47 133
        $this->pubkey_t = $secp256k1_pubkey_t;
48 133
        $this->compressed = $compressed;
49 133
    }
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
     */
65 6
    private function doEquals(self $other)
66
    {
67 6
        $context = $this->ecAdapter->getContext();
68 6
        $pubA = '';
69 6
        $pubB = '';
70 6
        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
        }
73
74 6
        return hash_equals($pubA, $pubB);
75
    }
76
77
    /**
78
     * @param PublicKeyInterface $other
79
     * @return bool
80
     */
81 6
    public function equals(PublicKeyInterface $other)
82
    {
83
        /** @var self $other */
84 6
        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
    }
86
87
    /**
88
     * @return bool|false
89
     */
90 119
    public function isCompressed()
91
    {
92 119
        return $this->compressed;
93
    }
94
95
    /**
96
     * @return resource
97
     */
98 115
    public function getResource()
99
    {
100 115
        return $this->pubkey_t;
101
    }
102
103
    /**
104
     * @return resource
105
     * @throws \Exception
106
     */
107 5
    private function clonePubkey()
108
    {
109 5
        $context = $this->ecAdapter->getContext();
110 5
        $serialized = '';
111 5
        if (1 !== secp256k1_ec_pubkey_serialize($context, $serialized, $this->pubkey_t, $this->compressed)) {
112
            throw new \Exception('Secp256k1: pubkey serialize');
113
        }
114
115
        /** @var resource $clone */
116 5
        $clone = '';
117 5
        if (1 !== secp256k1_ec_pubkey_parse($context, $clone, $serialized)) {
118
            throw new \Exception('Secp256k1 pubkey parse');
119
        }
120
121 5
        return $clone;
122
    }
123
124
    /**
125
     * @param \GMP $tweak
126
     * @return PublicKey
127
     * @throws \Exception
128
     */
129 4
    public function tweakAdd(\GMP $tweak)
130
    {
131 4
        $context = $this->ecAdapter->getContext();
132 4
        $bin = Buffer::int(gmp_strval($tweak, 10), 32)->getBinary();
133
134 4
        $clone = $this->clonePubkey();
135 4
        if (1 !== secp256k1_ec_pubkey_tweak_add($context, $clone, $bin)) {
136
            throw new \RuntimeException('Secp256k1: tweak add failed.');
137
        }
138
139 4
        return new PublicKey($this->ecAdapter, $clone, $this->compressed);
140
    }
141
142
    /**
143
     * @param \GMP $tweak
144
     * @return PublicKey
145
     * @throws \Exception
146
     */
147 1
    public function tweakMul(\GMP $tweak)
148
    {
149 1
        $context = $this->ecAdapter->getContext();
150 1
        $bin = Buffer::int(gmp_strval($tweak, 10), 32)->getBinary();
151
152 1
        $clone = $this->clonePubkey();
153 1
        if (1 !== secp256k1_ec_pubkey_tweak_mul($context, $clone, $bin)) {
154
            throw new \RuntimeException('Secp256k1: tweak mul failed.');
155
        }
156
157 1
        return new PublicKey($this->ecAdapter, $clone, $this->compressed);
158
    }
159
160
    /**
161
     * @return BufferInterface
162
     */
163 104
    public function getBuffer()
164
    {
165 104
        return (new PublicKeySerializer($this->ecAdapter))->serialize($this);
166
    }
167
}
168