Coverage Report

Created: 2026-04-29 19:21

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