LCOV - code coverage report
Current view: top level - src/rpc - signmessage.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 37 60 61.7 %
Date: 2023-09-26 12:08:55 Functions: 7 9 77.8 %

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

Generated by: LCOV version 1.14