| 156 | } |
| 157 | |
| 158 | static UniValue verifymessage(const JSONRPCRequest& request) |
| 159 | { |
| 160 | if (request.fHelp || request.params.size() != 3) |
| 161 | throw std::runtime_error( |
| 162 | "verifymessage \"address\" \"signature\" \"message\"\n" |
| 163 | "\nVerify a signed message\n" |
| 164 | "\nArguments:\n" |
| 165 | "1. \"address\" (string, required) The bitcoin address to use for the signature.\n" |
| 166 | "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n" |
| 167 | "3. \"message\" (string, required) The message that was signed.\n" |
| 168 | "\nResult:\n" |
| 169 | "true|false (boolean) If the signature is verified or not.\n" |
| 170 | "\nExamples:\n" |
| 171 | "\nUnlock the wallet for 30 seconds\n" |
| 172 | + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + |
| 173 | "\nCreate the signature\n" |
| 174 | + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") + |
| 175 | "\nVerify the signature\n" |
| 176 | + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") + |
| 177 | "\nAs json rpc\n" |
| 178 | + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"") |
| 179 | ); |
| 180 | |
| 181 | LOCK(cs_main); |
| 182 | |
| 183 | std::string strAddress = request.params[0].get_str(); |
| 184 | std::string strSign = request.params[1].get_str(); |
| 185 | std::string strMessage = request.params[2].get_str(); |
| 186 | |
| 187 | CTxDestination destination = DecodeDestination(strAddress); |
| 188 | if (!IsValidDestination(destination)) { |
| 189 | throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); |
| 190 | } |
| 191 | |
| 192 | const CKeyID *keyID = boost::get<CKeyID>(&destination); |
| 193 | if (!keyID) { |
| 194 | throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); |
| 195 | } |
| 196 | |
| 197 | bool fInvalid = false; |
| 198 | std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid); |
| 199 | |
| 200 | if (fInvalid) |
| 201 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); |
| 202 | |
| 203 | CHashWriter ss(SER_GETHASH, 0); |
| 204 | ss << strMessageMagic; |
| 205 | ss << strMessage; |
| 206 | |
| 207 | CPubKey pubkey; |
| 208 | if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) |
| 209 | return false; |
| 210 | |
| 211 | return (pubkey.GetID() == *keyID); |
| 212 | } |
| 213 | |
| 214 | static UniValue signmessagewithprivkey(const JSONRPCRequest& request) |
| 215 | { |
nothing calls this directly
no test coverage detected