Completed
Push — 0.0.35 ( b2fc74...d8d049 )
by thomas
28:12 queued 09:10
created

PublicKey   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 86%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 155
ccs 43
cts 50
cp 0.86
rs 10
c 1
b 0
f 0
wmc 19
lcom 1
cbo 4

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 4
A verify() 0 4 1
A doEquals() 0 11 3
A equals() 0 5 1
A isCompressed() 0 4 1
A getResource() 0 4 1
A clonePubkey() 0 16 3
A tweakAdd() 0 12 2
A tweakMul() 0 12 2
A getBuffer() 0 4 1
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 251
    public function __construct(EcAdapter $ecAdapter, $secp256k1_pubkey_t, $compressed = false)
36
    {
37 251
        if (!is_resource($secp256k1_pubkey_t) ||
38 251
            !get_resource_type($secp256k1_pubkey_t) === SECP256K1_TYPE_PUBKEY) {
39
            throw new \InvalidArgumentException('Secp256k1\Key\PublicKey expects ' . SECP256K1_TYPE_PUBKEY . ' resource');
40
        }
41
42 251
        if (false === is_bool($compressed)) {
43
            throw new \InvalidArgumentException('PublicKey: Compressed must be a boolean');
44
        }
45
46 251
        $this->ecAdapter = $ecAdapter;
47 251
        $this->pubkey_t = $secp256k1_pubkey_t;
48 251
        $this->compressed = $compressed;
49 251
    }
50
    
51
    /**
52
     * @param BufferInterface $msg32
53
     * @param SignatureInterface $signature
54
     * @return bool
55
     */
56 147
    public function verify(BufferInterface $msg32, SignatureInterface $signature)
57
    {
58 147
        return $this->ecAdapter->verify($msg32, $this, $signature);
59
    }
60
61
    /**
62
     * @param PublicKey $other
63
     * @return bool
64
     */
65 26
    private function doEquals(PublicKey $other)
66
    {
67 26
        $context = $this->ecAdapter->getContext();
68 26
        $pubA = '';
69 26
        $pubB = '';
70 26
        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 26
        return hash_equals($pubA, $pubB);
75
    }
76
77
    /**
78
     * @param PublicKeyInterface $other
79
     * @return bool
80
     */
81 26
    public function equals(PublicKeyInterface $other)
82
    {
83
        /** @var PublicKey $other */
84 26
        return $this->doEquals($other);
85
    }
86
87
    /**
88
     * @return bool|false
89
     */
90 116
    public function isCompressed()
91
    {
92 116
        return $this->compressed;
93
    }
94
95
    /**
96
     * @return resource
97
     */
98 233
    public function getResource()
99
    {
100 233
        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 98
    public function getBuffer()
164
    {
165 98
        return (new PublicKeySerializer($this->ecAdapter))->serialize($this);
166
    }
167
}
168