fuzz coverage

Coverage Report

Created: 2025-06-01 19:34

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