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