LCOV - code coverage report
Current view: top level - src/rpc - signmessage.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 36 60 60.0 %
Date: 2023-11-10 23:46:46 Functions: 3 8 37.5 %
Branches: 76 230 33.0 %

           Branch data     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                 :            :         },
      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