Completed
Pull Request — master (#334)
by thomas
147:16 queued 143:27
created

PublicKeySerializer::doSerialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 13
nc 2
nop 1
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 2
rs 9.4285
c 1
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Serializer\Key;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Key\PublicKeySerializerInterface;
7
use BitWasp\Buffertools\Buffer;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Adapter\EcAdapter;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key\PublicKey;
10
use BitWasp\Buffertools\BufferInterface;
11
use BitWasp\Buffertools\Parser;
12
use Mdanter\Ecc\Primitives\PointInterface;
13
14
class PublicKeySerializer implements PublicKeySerializerInterface
15
{
16
    /**
17
     * @var EcAdapter
18
     */
19
    private $ecAdapter;
20
21
    /**
22
     * @param EcAdapter $ecAdapter
23
     */
24 555
    public function __construct(EcAdapter $ecAdapter)
25
    {
26 555
        $this->ecAdapter = $ecAdapter;
27 555
    }
28
29
30
    /**
31
     * @param PublicKey $publicKey
32
     * @return null|string
33
     */
34 300
    public function getPrefix(PublicKey $publicKey)
35
    {
36 300
        if ($publicKey->getPrefix() === null) {
37 300
            return $publicKey->isCompressed()
38 222
                ? $this->ecAdapter->getMath()->isEven($publicKey->getPoint()->getY())
39 123
                    ? PublicKey::KEY_COMPRESSED_EVEN
40 152
                    : PublicKey::KEY_COMPRESSED_ODD
41 300
                : PublicKey::KEY_UNCOMPRESSED;
42
        } else {
43
            return $publicKey->getPrefix();
44
        }
45
46
    }
47
48
    /**
49
     * @param PublicKey $publicKey
50
     * @return BufferInterface
51
     */
52 300
    private function doSerialize(PublicKey $publicKey)
53
    {
54 300
        $math = $this->ecAdapter->getMath();
55 300
        $point = $publicKey->getPoint();
56 300
        $compressed = $publicKey->isCompressed();
57
58 300
        $parser = new Parser('', $math);
59 300
        $parser->writeBytes(1, new Buffer($this->getPrefix($publicKey)));
60
61 200
        $compressed
62 100
            ? $parser
63 183
            ->writeBytes(32, Buffer::int(gmp_strval($point->getX(), 10), null, $math))
64 61
            : $parser
65 144
            ->writeBytes(32, Buffer::int(gmp_strval($point->getX(), 10), null, $math))
66 144
            ->writeBytes(32, Buffer::int(gmp_strval($point->getY(), 10), null, $math));
67
68 300
        return $parser->getBuffer();
69
    }
70
71
    /**
72
     * @param PublicKeyInterface $publicKey
73
     * @return BufferInterface
74
     */
75 300
    public function serialize(PublicKeyInterface $publicKey)
76
    {
77
        /** @var PublicKey $publicKey */
78 300
        return $this->doSerialize($publicKey);
79
    }
80
81
    /**
82
     * @param BufferInterface|string $data
83
     * @return PublicKey
84
     * @throws \Exception
85
     */
86 426
    public function parse($data)
87
    {
88 426
        $buffer = (new Parser($data))->getBuffer();
89 426
        if (!in_array($buffer->getSize(), [PublicKey::LENGTH_COMPRESSED, PublicKey::LENGTH_UNCOMPRESSED], true)) {
90 18
            throw new \Exception('Invalid hex string, must match size of compressed or uncompressed public key');
91
        }
92
93 411
        return $this->ecAdapter->publicKeyFromBuffer($buffer);
94
    }
95
}
96