Branch data Line data Source code
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 : 2362 : static RPCHelpMan verifymessage()
18 : : {
19 : 2362 : return RPCHelpMan{"verifymessage",
20 [ + - ]: 4724 : "Verify a signed message.",
21 : : {
22 [ + - + - ]: 4724 : {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
23 [ + - + - ]: 4724 : {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
24 [ + - + - ]: 4724 : {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
25 : : },
26 [ + - ]: 4724 : RPCResult{
27 [ + - + - ]: 4724 : RPCResult::Type::BOOL, "", "If the signature is verified or not."
28 [ + - ]: 4724 : },
29 : 2362 : RPCExamples{
30 : : "\nUnlock the wallet for 30 seconds\n"
31 [ + - + - : 4724 : + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
+ - + - ]
32 : 2362 : "\nCreate the signature\n"
33 [ + - + - : 9448 : + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
+ - + - ]
34 : 2362 : "\nVerify the signature\n"
35 [ + - + - : 9448 : + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
+ - + - ]
36 : 2362 : "\nAs a JSON-RPC call\n"
37 [ + - + - : 9448 : + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
+ - + - ]
38 [ + - ]: 2362 : },
39 : 2362 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
40 : : {
41 [ + - + - : 13 : switch (MessageVerify(std::string{self.Arg<std::string_view>("address")},
+ - ]
42 [ + - + - ]: 26 : std::string{self.Arg<std::string_view>("signature")},
43 [ + + + + : 26 : std::string{self.Arg<std::string_view>("message")})) {
+ - ]
44 : 1 : case MessageVerificationResult::ERR_INVALID_ADDRESS:
45 [ + - + - ]: 2 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
46 : 2 : case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
47 [ + - + - ]: 4 : throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
48 : 1 : case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
49 [ + - + - ]: 2 : throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding");
50 : 2 : 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 : : }
56 : :
57 : 0 : return false;
58 : : },
59 [ + - + - : 16534 : };
+ + - - ]
60 [ + - + - : 14172 : }
+ - - - ]
61 : :
62 : 2351 : static RPCHelpMan signmessagewithprivkey()
63 : : {
64 : 2351 : return RPCHelpMan{
65 : 2351 : "signmessagewithprivkey",
66 [ + - ]: 4702 : "Sign a message with the private key of an address\n",
67 : : {
68 [ + - + - ]: 4702 : {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
69 [ + - + - ]: 4702 : {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
70 : : },
71 [ + - ]: 4702 : RPCResult{
72 [ + - + - ]: 4702 : RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
73 [ + - ]: 4702 : },
74 : 2351 : RPCExamples{
75 : : "\nCreate the signature\n"
76 [ + - + - : 4702 : + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
+ - + - ]
77 : 2351 : "\nVerify the signature\n"
78 [ + - + - : 9404 : + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
+ - + - ]
79 : 2351 : "\nAs a JSON-RPC call\n"
80 [ + - + - : 9404 : + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
+ - + - ]
81 [ + - ]: 2351 : },
82 : 2351 : [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
83 : : {
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 [ + - + - ]: 2 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
90 : : }
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 : : }
97 : :
98 [ + - ]: 1 : return signature;
99 : 3 : },
100 [ + - + - : 14106 : };
+ + - - ]
101 [ + - + - : 9404 : }
- - ]
102 : :
103 : 1299 : void RegisterSignMessageRPCCommands(CRPCTable& t)
104 : : {
105 : 1299 : static const CRPCCommand commands[]{
106 [ + - ]: 2334 : {"util", &verifymessage},
107 [ + - ]: 2334 : {"util", &signmessagewithprivkey},
108 [ + + + - : 3633 : };
+ - + - -
- ]
109 [ + + ]: 3897 : for (const auto& c : commands) {
110 : 2598 : t.appendCommand(c.name, &c);
111 : : }
112 : 1299 : }
|