Completed
Push — master ( 4c26fd...5c635d )
by thomas
106:46 queued 98:38
created

MessageSigner::calculateMessageHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
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\MessageSigner;
6
7
use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
8
use BitWasp\Bitcoin\Bitcoin;
9
use BitWasp\Bitcoin\Crypto\EcAdapter\Adapter\EcAdapterInterface;
10
use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PrivateKeyInterface;
11
use BitWasp\Bitcoin\Crypto\Hash;
12
use BitWasp\Bitcoin\Crypto\Random\Rfc6979;
13
use BitWasp\Bitcoin\Network\NetworkInterface;
14
use BitWasp\Buffertools\Buffer;
15
use BitWasp\Buffertools\BufferInterface;
16
use BitWasp\Buffertools\Buffertools;
17
18
class MessageSigner
19
{
20
    /**
21
     * @var EcAdapterInterface
22
     */
23
    private $ecAdapter;
24
25
    /**
26
     * @param EcAdapterInterface $ecAdapter
27
     */
28 10
    public function __construct(EcAdapterInterface $ecAdapter = null)
29
    {
30 10
        $this->ecAdapter = $ecAdapter ?: Bitcoin::getEcAdapter();
31 10
    }
32
33
    /**
34
     * @param NetworkInterface $network
35
     * @param string $message
36
     * @return Buffer
37
     */
38 10
    private function calculateBody(NetworkInterface $network, string $message)
39
    {
40 10
        $varIntBuffer = Buffertools::numToVarInt(strlen($message));
41 10
        return new Buffer("\x18{$network->getSignedMessageMagic()}:\n{$varIntBuffer->getBinary()}{$message}", null);
42
    }
43
44
    /**
45
     * @param NetworkInterface $network
46
     * @param string $message
47
     * @return BufferInterface
48
     */
49 10
    public function calculateMessageHash(NetworkInterface $network, string $message): BufferInterface
50
    {
51 10
        return Hash::sha256d($this->calculateBody($network, $message));
52
    }
53
54
    /**
55
     * @param SignedMessage $signedMessage
56
     * @param PayToPubKeyHashAddress $address
57
     * @param NetworkInterface|null $network
58
     * @return bool
59
     */
60 10
    public function verify(SignedMessage $signedMessage, PayToPubKeyHashAddress $address, NetworkInterface $network = null): bool
61
    {
62 10
        $network = $network ?: Bitcoin::getNetwork();
63 10
        $hash = $this->calculateMessageHash($network, $signedMessage->getMessage());
64
65 10
        $publicKey = $this->ecAdapter->recover(
66 10
            $hash,
67 10
            $signedMessage->getCompactSignature()
68
        );
69
70 10
        return $publicKey->getPubKeyHash()->equals($address->getHash());
71
    }
72
73
    /**
74
     * @param string $message
75
     * @param PrivateKeyInterface $privateKey
76
     * @param NetworkInterface|null $network
77
     * @return SignedMessage
78
     */
79 8
    public function sign(string $message, PrivateKeyInterface $privateKey, NetworkInterface $network = null): SignedMessage
80
    {
81 8
        $network = $network ?: Bitcoin::getNetwork();
82 8
        $hash = $this->calculateMessageHash($network, $message);
83
84 8
        return new SignedMessage(
85 8
            $message,
86 8
            $privateKey->signCompact(
87 8
                $hash,
88 8
                new Rfc6979(
89 8
                    $this->ecAdapter,
90 8
                    $privateKey,
91 8
                    $hash,
92 8
                    'sha256'
93
                )
94
            )
95
        );
96
    }
97
}
98