Bitcoin Core  27.99.0
P2P Digital Currency
signmessage.cpp
Go to the documentation of this file.
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 <key.h>
7 #include <key_io.h>
8 #include <rpc/protocol.h>
9 #include <rpc/request.h>
10 #include <rpc/server.h>
11 #include <rpc/util.h>
12 #include <univalue.h>
13 #include <util/message.h>
14 
15 #include <string>
16 
18 {
19  return RPCHelpMan{"verifymessage",
20  "Verify a signed message.",
21  {
22  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
23  {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
24  {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
25  },
26  RPCResult{
27  RPCResult::Type::BOOL, "", "If the signature is verified or not."
28  },
30  "\nUnlock the wallet for 30 seconds\n"
31  + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
32  "\nCreate the signature\n"
33  + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
34  "\nVerify the signature\n"
35  + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
36  "\nAs a JSON-RPC call\n"
37  + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
38  },
39  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
40  {
41  std::string strAddress = request.params[0].get_str();
42  std::string strSign = request.params[1].get_str();
43  std::string strMessage = request.params[2].get_str();
44 
45  switch (MessageVerify(strAddress, strSign, strMessage)) {
47  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
49  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
51  throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding");
54  return false;
56  return true;
57  }
58 
59  return false;
60  },
61  };
62 }
63 
65 {
66  return RPCHelpMan{"signmessagewithprivkey",
67  "\nSign a message with the private key of an address\n",
68  {
69  {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
70  {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
71  },
72  RPCResult{
73  RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
74  },
76  "\nCreate the signature\n"
77  + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
78  "\nVerify the signature\n"
79  + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
80  "\nAs a JSON-RPC call\n"
81  + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
82  },
83  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
84  {
85  std::string strPrivkey = request.params[0].get_str();
86  std::string strMessage = request.params[1].get_str();
87 
88  CKey key = DecodeSecret(strPrivkey);
89  if (!key.IsValid()) {
90  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
91  }
92 
93  std::string signature;
94 
95  if (!MessageSign(key, strMessage, signature)) {
96  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
97  }
98 
99  return signature;
100  },
101  };
102 }
103 
105 {
106  static const CRPCCommand commands[]{
107  {"util", &verifymessage},
108  {"util", &signmessagewithprivkey},
109  };
110  for (const auto& c : commands) {
111  t.appendCommand(c.name, &c);
112  }
113 }
An encapsulated private key.
Definition: key.h:33
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:119
RPC command dispatcher.
Definition: server.h:133
const std::string & get_str() const
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:209
@ ERR_MALFORMED_SIGNATURE
The provided signature couldn't be parsed (maybe invalid base64).
@ ERR_INVALID_ADDRESS
The provided address is invalid.
@ ERR_ADDRESS_NO_KEY
The provided address is valid but does not refer to a public key.
@ ERR_NOT_SIGNED
The message was not signed with the private key of the provided address.
@ OK
The message verification was successful.
@ ERR_PUBKEY_NOT_RECOVERED
A public key could not be recovered from the provided signature and message.
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
@ RPC_TYPE_ERROR
Unexpected type was passed as parameter.
Definition: protocol.h:40
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:41
void RegisterSignMessageRPCCommands(CRPCTable &t)
static RPCHelpMan signmessagewithprivkey()
Definition: signmessage.cpp:64
static RPCHelpMan verifymessage()
Definition: signmessage.cpp:17
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:155
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:173
@ NO
Required arg.
bool MessageSign(const CKey &privkey, const std::string &message, std::string &signature)
Sign a message.
Definition: message.cpp:57
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: message.cpp:26