Completed
Pull Request — master (#333)
by thomas
60:14 queued 55:22
created

PublicKey::tweakAdd()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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