signmessage.cpp
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 <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 { 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 }, 29 RPCExamples{ 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 switch (MessageVerify(std::string{self.Arg<std::string_view>("address")}, 42 std::string{self.Arg<std::string_view>("signature")}, 43 std::string{self.Arg<std::string_view>("message")})) { 44 case MessageVerificationResult::ERR_INVALID_ADDRESS: 45 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); 46 case MessageVerificationResult::ERR_ADDRESS_NO_KEY: 47 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); 48 case MessageVerificationResult::ERR_MALFORMED_SIGNATURE: 49 throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding"); 50 case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED: 51 case MessageVerificationResult::ERR_NOT_SIGNED: 52 return false; 53 case MessageVerificationResult::OK: 54 return true; 55 } 56 57 return false; 58 }, 59 }; 60 } 61 62 static RPCHelpMan signmessagewithprivkey() 63 { 64 return RPCHelpMan{ 65 "signmessagewithprivkey", 66 "Sign a message with the private key of an address\n", 67 { 68 {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."}, 69 {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, 70 }, 71 RPCResult{ 72 RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" 73 }, 74 RPCExamples{ 75 "\nCreate the signature\n" 76 + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + 77 "\nVerify the signature\n" 78 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") + 79 "\nAs a JSON-RPC call\n" 80 + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") 81 }, 82 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue 83 { 84 std::string strPrivkey = request.params[0].get_str(); 85 std::string strMessage = request.params[1].get_str(); 86 87 CKey key = DecodeSecret(strPrivkey); 88 if (!key.IsValid()) { 89 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); 90 } 91 92 std::string signature; 93 94 if (!MessageSign(key, strMessage, signature)) { 95 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); 96 } 97 98 return signature; 99 }, 100 }; 101 } 102 103 void RegisterSignMessageRPCCommands(CRPCTable& t) 104 { 105 static const CRPCCommand commands[]{ 106 {"util", &verifymessage}, 107 {"util", &signmessagewithprivkey}, 108 }; 109 for (const auto& c : commands) { 110 t.appendCommand(c.name, &c); 111 } 112 }