Passed
Push — master ( 280df4...3ba82a )
by thomas
51:58 queued 49:57
created

SignedMessageSerializer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Serializer\MessageSigner;
6
7
use BitWasp\Bitcoin\Crypto\EcAdapter\Serializer\Signature\CompactSignatureSerializerInterface;
8
use BitWasp\Bitcoin\MessageSigner\SignedMessage;
9
use BitWasp\Buffertools\Buffer;
10
use BitWasp\Buffertools\BufferInterface;
11
12
class SignedMessageSerializer
13
{
14
15
    // Message headers
16
    const HEADER = '-----BEGIN BITCOIN SIGNED MESSAGE-----';
17
    const SIG_START = '-----BEGIN SIGNATURE-----';
18
    const FOOTER = '-----END BITCOIN SIGNED MESSAGE-----';
19
20
    /**
21
     * @var CompactSignatureSerializerInterface
22
     */
23
    private $csSerializer;
24
25
    /**
26
     * @param CompactSignatureSerializerInterface $csSerializer
27
     */
28 8
    public function __construct(CompactSignatureSerializerInterface $csSerializer)
29
    {
30 8
        $this->csSerializer = $csSerializer;
31 8
    }
32
33
    /**
34
     * @param SignedMessage $signedMessage
35
     * @return BufferInterface
36
     */
37 2
    public function serialize(SignedMessage $signedMessage): BufferInterface
38
    {
39 2
        $content = self::HEADER . PHP_EOL
40 2
            . $signedMessage->getMessage() . PHP_EOL
41 2
            . self::SIG_START . PHP_EOL
42 2
            . base64_encode($signedMessage->getCompactSignature()->getBinary()) . PHP_EOL
43 2
            . self::FOOTER;
44
45 2
        return new Buffer($content);
46
    }
47
48
    /**
49
     * @param string $content
50
     * @return SignedMessage
51
     */
52 8
    public function parse(string $content): SignedMessage
53
    {
54 8
        if (0 !== strpos($content, self::HEADER)) {
55 2
            throw new \RuntimeException('Message must begin with ' . self::HEADER);
56
        }
57
58 6
        $sigHeaderPos = strpos($content, self::SIG_START);
59 6
        if (false === $sigHeaderPos) {
60 2
            throw new \RuntimeException('Unable to find start of signature');
61
        }
62
63 4
        $sigEnd = strlen($content) - strlen(self::FOOTER);
64 4
        if (strpos($content, self::FOOTER) !== $sigEnd) {
65 2
            throw new \RuntimeException('Message must end with ' . self::FOOTER);
66
        }
67
68 2
        $messageStartPos = strlen(self::HEADER) + 1;
69 2
        $messageEndPos = $sigHeaderPos - $messageStartPos - 1;
70 2
        $message = substr($content, $messageStartPos, $messageEndPos);
71
72 2
        $sigStart = $sigHeaderPos + strlen(self::SIG_START);
73
74 2
        $sig = trim(substr($content, $sigStart, $sigEnd - $sigStart));
75 2
        $decoded = base64_decode($sig);
76 2
        if (false === $decoded) {
77
            throw new \RuntimeException('Invalid base64');
78
        }
79
80 2
        $compactSig = $this->csSerializer->parse(new Buffer($decoded));
81
82 2
        return new SignedMessage($message, $compactSig);
83
    }
84
}
85