Completed
Pull Request — master (#591)
by thomas
30:19 queued 12s
created

PublicKey::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 4
dl 0
loc 11
ccs 6
cts 6
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key;
6
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Adapter\EcAdapter;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Serializer\Key\PublicKeySerializer;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\Key;
10
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\KeyInterface;
11
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
12
use BitWasp\Bitcoin\Crypto\EcAdapter\Signature\SignatureInterface;
13
use BitWasp\Buffertools\BufferInterface;
14
use Mdanter\Ecc\Primitives\PointInterface;
15
16
class PublicKey extends Key implements PublicKeyInterface, \Mdanter\Ecc\Crypto\Key\PublicKeyInterface
17
{
18
    /**
19
     * @var EcAdapter
20
     */
21
    private $ecAdapter;
22
23
    /**
24
     * @var PointInterface
25
     */
26
    private $point;
27
28
    /**
29
     * @var string
30
     */
31
    private $prefix;
32
33
    /**
34
     * @var bool
35
     */
36
    private $compressed;
37
38
    /**
39
     * PublicKey constructor.
40
     * @param EcAdapter $ecAdapter
41
     * @param PointInterface $point
42
     * @param bool $compressed
43
     * @param string $prefix
44
     */
45 304
    public function __construct(
46
        EcAdapter $ecAdapter,
47
        PointInterface $point,
48
        bool $compressed = false,
49
        string $prefix = null
50
    ) {
51 304
        $this->ecAdapter = $ecAdapter;
52 304
        $this->point = $point;
53 304
        $this->prefix = $prefix;
54 304
        $this->compressed = $compressed;
55 304
    }
56
57
    /**
58
     * @return \Mdanter\Ecc\Primitives\GeneratorPoint
59
     */
60 193
    public function getGenerator()
61
    {
62 193
        return $this->ecAdapter->getGenerator();
63
    }
64
65
    /**
66
     * @return \Mdanter\Ecc\Primitives\CurveFpInterface
67
     */
68
    public function getCurve()
69
    {
70
        return $this->ecAdapter->getGenerator()->getCurve();
71
    }
72
73
    /**
74
     * @return string
75
     */
76 141
    public function getPrefix()
77
    {
78 141
        return $this->prefix;
79
    }
80
81
    /**
82
     * @return PointInterface
83
     */
84 282
    public function getPoint(): PointInterface
85
    {
86 282
        return $this->point;
87
    }
88
89
    /**
90
     * @param BufferInterface $msg32
91
     * @param SignatureInterface $signature
92
     * @return bool
93
     */
94
    public function verify(BufferInterface $msg32, SignatureInterface $signature): bool
95
    {
96
        return $this->ecAdapter->verify($msg32, $this, $signature);
97
    }
98
99
    /**
100
     * @param \GMP $tweak
101
     * @return KeyInterface
102
     */
103 4
    public function tweakAdd(\GMP $tweak): KeyInterface
104
    {
105 4
        $offset = $this->ecAdapter->getGenerator()->mul($tweak);
106 4
        $newPoint = $this->point->add($offset);
107 4
        return $this->ecAdapter->getPublicKey($newPoint, $this->compressed);
108
    }
109
110
    /**
111
     * @param \GMP $tweak
112
     * @return KeyInterface
113
     */
114 1
    public function tweakMul(\GMP $tweak): KeyInterface
115
    {
116 1
        $point = $this->point->mul($tweak);
117 1
        return $this->ecAdapter->getPublicKey($point, $this->compressed);
118
    }
119
120
    /**
121
     * @param BufferInterface $publicKey
122
     * @return bool
123
     */
124 67
    public static function isCompressedOrUncompressed(BufferInterface $publicKey): bool
125
    {
126 67
        $vchPubKey = $publicKey->getBinary();
127 67
        if ($publicKey->getSize() < self::LENGTH_COMPRESSED) {
128 3
            return false;
129
        }
130
131 65
        if ($vchPubKey[0] === self::KEY_UNCOMPRESSED) {
132 12
            if ($publicKey->getSize() !== self::LENGTH_UNCOMPRESSED) {
133
                // Invalid length for uncompressed key
134 12
                return false;
135
            }
136 57
        } elseif (in_array($vchPubKey[0], [
137 57
            self::KEY_COMPRESSED_EVEN,
138 57
            self::KEY_COMPRESSED_ODD
139
        ])) {
140 49
            if ($publicKey->getSize() !== self::LENGTH_COMPRESSED) {
141 49
                return false;
142
            }
143
        } else {
144 9
            return false;
145
        }
146
147 56
        return true;
148
    }
149
150
    /**
151
     * @return bool
152
     */
153 155
    public function isCompressed(): bool
154
    {
155 155
        return $this->compressed;
156
    }
157
158
    /**
159
     * @param PublicKey $other
160
     * @return bool
161
     */
162 58
    private function doEquals(PublicKey $other): bool
163
    {
164 58
        return $this->compressed === $other->compressed
165 58
            && $this->point->equals($other->point)
166 58
            && (($this->prefix === null || $other->prefix === null) || ($this->prefix === $other->prefix));
167
    }
168
169
    /**
170
     * @param PublicKeyInterface $other
171
     * @return bool
172
     */
173 58
    public function equals(PublicKeyInterface $other): bool
174
    {
175
        /** @var self $other */
176 58
        return $this->doEquals($other);
177
    }
178
179
    /**
180
     * @return BufferInterface
181
     */
182 119
    public function getBuffer(): BufferInterface
183
    {
184 119
        return (new PublicKeySerializer($this->ecAdapter))->serialize($this);
185
    }
186
}
187