/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 | } |