Completed
Push — master ( 29ec42...778040 )
by thomas
9s
created

DerSignatureSerializer::getOuterTemplate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1.0233

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 7
ccs 5
cts 7
cp 0.7143
crap 1.0233
rs 9.4285
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\Adapter\EcAdapterInterface;
6
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Adapter\EcAdapter;
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\Secp256k1\Signature\Signature;
8
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Signature\DerSignatureSerializerInterface;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Signature\SignatureInterface;
10
use BitWasp\Buffertools\Buffer;
11
use BitWasp\Buffertools\Parser;
12
use BitWasp\Buffertools\Template;
13
use BitWasp\Buffertools\TemplateFactory;
14
15
class DerSignatureSerializer implements DerSignatureSerializerInterface
16
{
17
    /**
18
     * @var EcAdapter
19
     */
20
    private $ecAdapter;
21
22
    /**
23
     * @param EcAdapter $ecAdapter
24
     */
25 18
    public function __construct(EcAdapter $ecAdapter)
26
    {
27 18
        $this->ecAdapter = $ecAdapter;
28 18
    }
29
30
    /**
31
     * @return EcAdapterInterface
32
     */
33 14
    public function getEcAdapter()
34
    {
35 14
        return $this->ecAdapter;
36
    }
37
38
    /**
39
     * @param Signature $signature
40
     * @return Buffer
41
     */
42 16
    private function doSerialize(Signature $signature)
43
    {
44 16
        $signatureOut = '';
45 16
        if (!secp256k1_ecdsa_signature_serialize_der($this->ecAdapter->getContext(), $signatureOut, $signature->getResource())) {
46
            throw new \RuntimeException('Secp256k1: serialize der failure');
47
        }
48
49 16
        return new Buffer($signatureOut);
50
    }
51
52
    /**
53
     * @param SignatureInterface $signature
54
     * @return Buffer
55
     */
56 16
    public function serialize(SignatureInterface $signature)
57
    {
58
        /** @var Signature $signature */
59 16
        return $this->doSerialize($signature);
60
    }
61
62
    /**
63
     * @return Template
64
     */
65 15
    private function getInnerTemplate()
66
    {
67 15
        return (new TemplateFactory())
68 15
            ->uint8()
69 15
            ->varstring()
70 15
            ->uint8()
71 15
            ->varstring()
72 15
            ->getTemplate();
73
    }
74
75
    /**
76
     * @return Template
77
     */
78 15
    private function getOuterTemplate()
79
    {
80 15
        return (new TemplateFactory())
81 15
            ->uint8()
82 15
            ->varstring()
83 15
            ->getTemplate();
84
    }
85
86
    /**
87
     * @param $data
88
     * @return SignatureInterface
89
     */
90 16
    public function parse($data)
91
    {
92 16
        $buffer = (new Parser($data))->getBuffer();
93 16
        $binary = $buffer->getBinary();
94
95 16
        $sig_t = '';
96
        /** @var resource $sig_t */
97 16
        if (!secp256k1_ecdsa_signature_parse_der($this->ecAdapter->getContext(), $sig_t, $binary)) {
98 1
            throw new \RuntimeException('Secp256k1: parse der failure');
99
        }
100
101
        // Unfortunately, we need to use the Parser here to get r and s :/
102 15
        list (, $inner) = $this->getOuterTemplate()->parse(new Parser($buffer));
103 15
        list (, $r, , $s) = $this->getInnerTemplate()->parse(new Parser($inner));
104
        /** @var Buffer $r */
105
        /** @var Buffer $s */
106
107 15
        return new Signature($this->ecAdapter, gmp_init($r->getInt(), 10), gmp_init($s->getInt(), 10), $sig_t);
108
    }
109
}
110