Completed
Pull Request — master (#446)
by thomas
105:00 queued 101:56
created

WifPrivateKeySerializer::parse()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5.009

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 8
nop 2
dl 0
loc 22
ccs 13
cts 14
cp 0.9286
crap 5.009
rs 8.6737
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Serializer\Key\PrivateKey;
4
5
use BitWasp\Bitcoin\Base58;
6
use BitWasp\Bitcoin\Bitcoin;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PrivateKeyInterface;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Key\PrivateKeySerializerInterface;
9
use BitWasp\Bitcoin\Exceptions\Base58ChecksumFailure;
10
use BitWasp\Bitcoin\Exceptions\InvalidPrivateKey;
11
use BitWasp\Bitcoin\Key\PrivateKeyFactory;
12
use BitWasp\Bitcoin\Math\Math;
13
use BitWasp\Bitcoin\Network\NetworkInterface;
14
use BitWasp\Buffertools\Buffer;
15
use BitWasp\Buffertools\Buffertools;
16
17
class WifPrivateKeySerializer
18
{
19
    /**
20
     * @var Math
21
     */
22
    private $math;
23
24
    /**
25
     * @var PrivateKeySerializerInterface
26
     */
27
    private $keySerializer;
28
29
    /**
30
     * @param Math $math
31
     * @param PrivateKeySerializerInterface $serializer
32
     */
33 12
    public function __construct(Math $math, PrivateKeySerializerInterface $serializer)
34
    {
35 12
        $this->math = $math;
36 12
        $this->keySerializer = $serializer;
37 12
    }
38
39
    /**
40
     * @param NetworkInterface $network
41
     * @param PrivateKeyInterface $privateKey
42
     * @return string
43
     */
44 8
    public function serialize(NetworkInterface $network, PrivateKeyInterface $privateKey)
45
    {
46 8
        $serialized = Buffertools::concat(
47 8
            Buffer::hex($network->getPrivByte(), 1, $this->math),
48 8
            $this->keySerializer->serialize($privateKey)
49
        );
50
51 8
        if ($privateKey->isCompressed()) {
52 6
            $serialized = Buffertools::concat(
53
                $serialized,
54 6
                new Buffer("\x01", 1, $this->math)
55
            );
56
        }
57
58 8
        return Base58::encodeCheck($serialized);
59
    }
60
61
    /**
62
     * @param string $wif
63
     * @param NetworkInterface|null $network
64
     * @return PrivateKeyInterface
65
     * @throws Base58ChecksumFailure
66
     * @throws InvalidPrivateKey
67
     */
68 6
    public function parse($wif, NetworkInterface $network = null)
69
    {
70 6
        $network = $network ?: Bitcoin::getNetwork();
71 6
        $data = Base58::decodeCheck($wif);
72 4
        if ($data->slice(0, 1)->getHex() !== $network->getPrivByte()) {
73
            throw new \RuntimeException('WIF prefix does not match networks');
74
        }
75
76 4
        $payload = $data->slice(1);
77 4
        $size = $payload->getSize();
78
79 4
        if (33 === $size) {
80 2
            $compressed = true;
81 2
            $payload = $payload->slice(0, 32);
82 4
        } else if (32 === $size) {
83 4
            $compressed = false;
84
        } else {
85 2
            throw new InvalidPrivateKey("Private key should be always be 32 or 33 bytes (depending on if it's compressed)");
86
        }
87
88 4
        return PrivateKeyFactory::fromInt($payload->getInt(), $compressed);
89
    }
90
}
91