Completed
Push — 0.0.35 ( b2fc74...d8d049 )
by thomas
28:12 queued 09:10
created

CompactSignatureSerializer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Serializer\Signature;
4
5
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Adapter\EcAdapter;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Signature\CompactSignature;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Signature\CompactSignatureSerializerInterface;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Signature\CompactSignatureInterface;
9
use BitWasp\Buffertools\Buffer;
10
use BitWasp\Buffertools\BufferInterface;
11
use BitWasp\Buffertools\Parser;
12
13
class CompactSignatureSerializer implements CompactSignatureSerializerInterface
14
{
15
    /**
16
     * @var EcAdapter
17
     */
18
    private $ecAdapter;
19
20
    /**
21
     * @param EcAdapter $ecAdapter
22
     */
23 11
    public function __construct(EcAdapter $ecAdapter)
24
    {
25 11
        $this->ecAdapter = $ecAdapter;
26 11
    }
27
28
    /**
29
     * @param CompactSignature $signature
30
     * @return BufferInterface
31
     */
32 5
    private function doSerialize(CompactSignature $signature)
33
    {
34 5
        $sig_t = '';
35 5
        $recid = '';
36 5
        if (!secp256k1_ecdsa_recoverable_signature_serialize_compact($this->ecAdapter->getContext(), $signature->getResource(), $sig_t, $recid)) {
37
            throw new \RuntimeException('Secp256k1 serialize compact failure');
38
        }
39
40 5
        return new Buffer(chr((int)$signature->getFlags()) . $sig_t, 65, $this->ecAdapter->getMath());
41
    }
42
43
    /**
44
     * @param CompactSignatureInterface $signature
45
     * @return BufferInterface
46
     */
47 5
    public function serialize(CompactSignatureInterface $signature)
48
    {
49
        /** @var CompactSignature $signature */
50 5
        return $this->doSerialize($signature);
51
    }
52
53
    /**
54
     * @param string|BufferInterface $data
55
     * @return CompactSignature
56
     */
57 7
    public function parse($data)
58
    {
59 7
        $math = $this->ecAdapter->getMath();
60 7
        $buffer = (new Parser($data, $math))->getBuffer();
61
62 7
        if ($buffer->getSize() !== 65) {
63 1
            throw new \RuntimeException('Compact Sig must be 65 bytes');
64
        }
65
66 6
        $byte = (int) $buffer->slice(0, 1)->getInt();
67 6
        $sig = $buffer->slice(1, 64);
68
69 6
        $recoveryFlags = $byte - 27;
70 6
        if ($recoveryFlags > 7) {
71
            throw new \RuntimeException('Invalid signature type');
72
        }
73
74 6
        $isCompressed = $math->cmp($math->bitwiseAnd(gmp_init($recoveryFlags), gmp_init(4)), gmp_init(0)) !== 0;
75 6
        $recoveryId = $recoveryFlags - ($isCompressed ? 4 : 0);
76
77 6
        $sig_t = '';
78
        /** @var resource $sig_t */
79 6
        if (!secp256k1_ecdsa_recoverable_signature_parse_compact($this->ecAdapter->getContext(), $sig_t, $sig->getBinary(), $recoveryId)) {
80
            throw new \RuntimeException('Unable to parse compact signature');
81
        }
82
83 6
        return new CompactSignature($this->ecAdapter, $sig_t, $recoveryId, $isCompressed);
84
    }
85
}
86