Completed
Pull Request — master (#359)
by Ruben de
14:27
created

PublicKeySerializer::serialize()   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\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 185
    public function __construct(EcAdapter $ecAdapter)
25
    {
26 185
        $this->ecAdapter = $ecAdapter;
27 185
    }
28
29
    /**
30
     * @param PublicKey $publicKey
31
     * @return string
32
     */
33 100
    public function getPrefix(PublicKey $publicKey)
34
    {
35 100
        if (null === $publicKey->getPrefix()) {
36 58
            return $publicKey->isCompressed()
37 35
                ? $this->ecAdapter->getMath()->isEven($publicKey->getPoint()->getY())
38 18
                    ? PublicKey::KEY_COMPRESSED_EVEN
39 35
                    : PublicKey::KEY_COMPRESSED_ODD
40 58
                : PublicKey::KEY_UNCOMPRESSED;
41
        } else {
42 52
            return $publicKey->getPrefix();
43
        }
44
    }
45
46
    /**
47
     * @param PublicKey $publicKey
48
     * @return BufferInterface
49
     */
50 100
    private function doSerialize(PublicKey $publicKey)
51
    {
52 100
        $math = $this->ecAdapter->getMath();
53 100
        $point = $publicKey->getPoint();
54 100
        $compressed = $publicKey->isCompressed();
55
56 100
        $parser = new Parser('', $math);
57 100
        $parser->writeBytes(1, new Buffer($this->getPrefix($publicKey)));
58
59 100
        $compressed
60
            ? $parser
61 61
            ->writeBytes(32, Buffer::int(gmp_strval($point->getX(), 10), null, $math))
62
            : $parser
63 48
            ->writeBytes(32, Buffer::int(gmp_strval($point->getX(), 10), null, $math))
64 48
            ->writeBytes(32, Buffer::int(gmp_strval($point->getY(), 10), null, $math));
65
66 100
        return $parser->getBuffer();
67
    }
68
69
    /**
70
     * @param PublicKeyInterface $publicKey
71
     * @return BufferInterface
72
     */
73 100
    public function serialize(PublicKeyInterface $publicKey)
74
    {
75
        /** @var PublicKey $publicKey */
76 100
        return $this->doSerialize($publicKey);
77
    }
78
79
    /**
80
     * @param BufferInterface|string $data
81
     * @return PublicKey
82
     * @throws \Exception
83
     */
84 142
    public function parse($data)
85
    {
86 142
        $buffer = (new Parser($data))->getBuffer();
87 142
        if (!in_array($buffer->getSize(), [PublicKey::LENGTH_COMPRESSED, PublicKey::LENGTH_UNCOMPRESSED], true)) {
88 6
            throw new \Exception('Invalid hex string, must match size of compressed or uncompressed public key');
89
        }
90
91 137
        return $this->ecAdapter->publicKeyFromBuffer($buffer);
92
    }
93
}
94