Coverage Report

Created: 2026-09-14 20:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/rpc/signmessage.cpp
Line
Count
Source
1
// Copyright (c) 2010 Satoshi Nakamoto
2
// Copyright (c) 2009-present 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 <rpc/register.h> // IWYU pragma: associated
8
9
#include <key.h>
10
#include <key_io.h>
11
#include <rpc/protocol.h>
12
#include <rpc/request.h>
13
#include <rpc/server.h>
14
#include <rpc/util.h>
15
#include <univalue.h>
16
17
#include <string>
18
#include <string_view>
19
#include <vector>
20
21
static RPCMethod verifymessage()
22
2.48k
{
23
2.48k
    return RPCMethod{"verifymessage",
24
2.48k
        "Verify a signed message.",
25
2.48k
        {
26
2.48k
            {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
27
2.48k
            {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
28
2.48k
            {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
29
2.48k
        },
30
2.48k
        RPCResult{
31
2.48k
            RPCResult::Type::BOOL, "", "If the signature is verified or not."
32
2.48k
        },
33
2.48k
        RPCExamples{
34
2.48k
            "\nUnlock the wallet for 30 seconds\n"
35
2.48k
            + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
36
2.48k
            "\nCreate the signature\n"
37
2.48k
            + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
38
2.48k
            "\nVerify the signature\n"
39
2.48k
            + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
40
2.48k
            "\nAs a JSON-RPC call\n"
41
2.48k
            + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
42
2.48k
        },
43
2.48k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
44
2.48k
        {
45
13
            switch (MessageVerify(std::string{self.Arg<std::string_view>("address")},
46
13
                                  std::string{self.Arg<std::string_view>("signature")},
47
13
                                  std::string{self.Arg<std::string_view>("message")})) {
48
1
            case MessageVerificationResult::ERR_INVALID_ADDRESS:
49
1
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
50
2
            case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
51
2
                throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
52
1
            case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
53
1
                throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding");
54
0
            case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED:
55
2
            case MessageVerificationResult::ERR_NOT_SIGNED:
56
2
                return false;
57
7
            case MessageVerificationResult::OK:
58
7
                return true;
59
13
            }
60
61
0
            return false;
62
13
        },
63
2.48k
    };
64
2.48k
}
65
66
static RPCMethod signmessagewithprivkey()
67
2.47k
{
68
2.47k
    return RPCMethod{
69
2.47k
        "signmessagewithprivkey",
70
2.47k
        "Sign a message with the private key of an address\n",
71
2.47k
        {
72
2.47k
            {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
73
2.47k
            {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
74
2.47k
        },
75
2.47k
        RPCResult{
76
2.47k
            RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
77
2.47k
        },
78
2.47k
        RPCExamples{
79
2.47k
            "\nCreate the signature\n"
80
2.47k
            + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
81
2.47k
            "\nVerify the signature\n"
82
2.47k
            + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
83
2.47k
            "\nAs a JSON-RPC call\n"
84
2.47k
            + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
85
2.47k
        },
86
2.47k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
87
2.47k
        {
88
2
            std::string strPrivkey = request.params[0].get_str();
89
2
            std::string strMessage = request.params[1].get_str();
90
91
2
            CKey key = DecodeSecret(strPrivkey);
92
2
            if (!key.IsValid()) {
93
1
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
94
1
            }
95
96
1
            std::string signature;
97
98
1
            if (!MessageSign(key, strMessage, signature)) {
99
0
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
100
0
            }
101
102
1
            return signature;
103
1
        },
104
2.47k
    };
105
2.47k
}
106
107
void RegisterSignMessageRPCCommands(CRPCTable& t)
108
1.36k
{
109
1.36k
    static const CRPCCommand commands[]{
110
1.36k
        {"util", &verifymessage},
111
1.36k
        {"util", &signmessagewithprivkey},
112
1.36k
    };
113
2.72k
    for (const auto& c : commands) {
114
2.72k
        t.appendCommand(c.name, &c);
115
2.72k
    }
116
1.36k
}