Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-2022 The Bitcoin Core developers
3 : : // Distributed under the MIT software license, see the accompanying
4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 : :
6 : : #include <common/signmessage.h>
7 : : #include <hash.h>
8 : : #include <key.h>
9 : : #include <key_io.h>
10 : : #include <pubkey.h>
11 : : #include <uint256.h>
12 : : #include <util/strencodings.h>
13 : :
14 : : #include <cassert>
15 : : #include <optional>
16 : : #include <string>
17 : : #include <variant>
18 : : #include <vector>
19 : :
20 : : /**
21 : : * Text used to signify that a signed message follows and to prevent
22 : : * inadvertently signing a transaction.
23 : : */
24 [ + - ]: 1 : const std::string MESSAGE_MAGIC = "Bitcoin Signed Message:\n";
25 : :
26 : 1588 : MessageVerificationResult MessageVerify(
27 : : const std::string& address,
28 : : const std::string& signature,
29 : : const std::string& message)
30 : : {
31 : 1588 : CTxDestination destination = DecodeDestination(address);
32 [ + - + + ]: 1588 : if (!IsValidDestination(destination)) {
33 : 781 : return MessageVerificationResult::ERR_INVALID_ADDRESS;
34 : : }
35 : :
36 [ + + ]: 807 : if (std::get_if<PKHash>(&destination) == nullptr) {
37 : 82 : return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
38 : : }
39 : :
40 [ + - ]: 725 : auto signature_bytes = DecodeBase64(signature);
41 [ + + ]: 725 : if (!signature_bytes) {
42 : 1 : return MessageVerificationResult::ERR_MALFORMED_SIGNATURE;
43 : : }
44 : :
45 [ + - ]: 724 : CPubKey pubkey;
46 [ + - + - : 724 : if (!pubkey.RecoverCompact(MessageHash(message), *signature_bytes)) {
+ + ]
47 : 11 : return MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED;
48 : : }
49 : :
50 [ + - + + ]: 713 : if (!(PKHash(pubkey) == *std::get_if<PKHash>(&destination))) {
51 : 25 : return MessageVerificationResult::ERR_NOT_SIGNED;
52 : : }
53 : :
54 : 688 : return MessageVerificationResult::OK;
55 : 1588 : }
56 : :
57 : 2375 : bool MessageSign(
58 : : const CKey& privkey,
59 : : const std::string& message,
60 : : std::string& signature)
61 : : {
62 : 2375 : std::vector<unsigned char> signature_bytes;
63 : :
64 [ + - + - : 2375 : if (!privkey.SignCompact(MessageHash(message), signature_bytes)) {
+ + ]
65 : 80 : return false;
66 : : }
67 : :
68 [ + - + - ]: 2295 : signature = EncodeBase64(signature_bytes);
69 : :
70 : 2295 : return true;
71 : 2375 : }
72 : :
73 : 3866 : uint256 MessageHash(const std::string& message)
74 : : {
75 : 3866 : HashWriter hasher{};
76 : 3866 : hasher << MESSAGE_MAGIC << message;
77 : :
78 : 3866 : return hasher.GetHash();
79 : 3866 : }
80 : :
81 : 767 : std::string SigningResultString(const SigningResult res)
82 : : {
83 [ - + + + ]: 767 : switch (res) {
84 : : case SigningResult::OK:
85 [ + - ]: 720 : return "No error";
86 : : case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
87 [ + - ]: 25 : return "Private key not available";
88 : : case SigningResult::SIGNING_FAILED:
89 [ + - ]: 22 : return "Sign failed";
90 : : // no default case, so the compiler can warn about missing cases
91 : : }
92 : 0 : assert(false);
93 : 767 : }
|