mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-05-22 01:40:48 +02:00
rpc: Move signmessage RPC util to new file
Can be reviewed with --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space
This commit is contained in:
parent
fa9425177e
commit
fa60169811
@ -38,7 +38,11 @@ if [ "${RUN_TIDY}" = "true" ]; then
|
|||||||
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/src/"
|
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/src/"
|
||||||
CI_EXEC run-clang-tidy "${MAKEJOBS}"
|
CI_EXEC run-clang-tidy "${MAKEJOBS}"
|
||||||
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/"
|
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/"
|
||||||
CI_EXEC "python3 ${BASE_SCRATCH_DIR}/iwyu/include-what-you-use/iwyu_tool.py src/compat src/init -p . ${MAKEJOBS} -- -Xiwyu --cxx17ns -Xiwyu --mapping_file=${BASE_BUILD_DIR}/bitcoin-$HOST/contrib/devtools/iwyu/bitcoin.core.imp"
|
CI_EXEC "python3 ${BASE_SCRATCH_DIR}/iwyu/include-what-you-use/iwyu_tool.py"\
|
||||||
|
" src/compat"\
|
||||||
|
" src/init"\
|
||||||
|
" src/rpc/signmessage.cpp"\
|
||||||
|
" -p . ${MAKEJOBS} -- -Xiwyu --cxx17ns -Xiwyu --mapping_file=${BASE_BUILD_DIR}/bitcoin-$HOST/contrib/devtools/iwyu/bitcoin.core.imp"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$RUN_SECURITY_TESTS" = "true" ]; then
|
if [ "$RUN_SECURITY_TESTS" = "true" ]; then
|
||||||
|
@ -382,6 +382,7 @@ libbitcoin_node_a_SOURCES = \
|
|||||||
rpc/rawtransaction.cpp \
|
rpc/rawtransaction.cpp \
|
||||||
rpc/server.cpp \
|
rpc/server.cpp \
|
||||||
rpc/server_util.cpp \
|
rpc/server_util.cpp \
|
||||||
|
rpc/signmessage.cpp \
|
||||||
rpc/txoutproof.cpp \
|
rpc/txoutproof.cpp \
|
||||||
script/sigcache.cpp \
|
script/sigcache.cpp \
|
||||||
shutdown.cpp \
|
shutdown.cpp \
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include <script/descriptor.h>
|
#include <script/descriptor.h>
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
#include <util/message.h> // For MessageSign(), MessageVerify()
|
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
#include <util/syscall_sandbox.h>
|
#include <util/syscall_sandbox.h>
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
@ -309,93 +308,6 @@ static RPCHelpMan deriveaddresses()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static RPCHelpMan verifymessage()
|
|
||||||
{
|
|
||||||
return RPCHelpMan{"verifymessage",
|
|
||||||
"Verify a signed message.",
|
|
||||||
{
|
|
||||||
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
|
|
||||||
{"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
|
|
||||||
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
|
|
||||||
},
|
|
||||||
RPCResult{
|
|
||||||
RPCResult::Type::BOOL, "", "If the signature is verified or not."
|
|
||||||
},
|
|
||||||
RPCExamples{
|
|
||||||
"\nUnlock the wallet for 30 seconds\n"
|
|
||||||
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
|
|
||||||
"\nCreate the signature\n"
|
|
||||||
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
|
|
||||||
"\nVerify the signature\n"
|
|
||||||
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
|
|
||||||
"\nAs a JSON-RPC call\n"
|
|
||||||
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
|
|
||||||
},
|
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
|
||||||
{
|
|
||||||
std::string strAddress = request.params[0].get_str();
|
|
||||||
std::string strSign = request.params[1].get_str();
|
|
||||||
std::string strMessage = request.params[2].get_str();
|
|
||||||
|
|
||||||
switch (MessageVerify(strAddress, strSign, strMessage)) {
|
|
||||||
case MessageVerificationResult::ERR_INVALID_ADDRESS:
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
|
||||||
case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
|
|
||||||
case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding");
|
|
||||||
case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED:
|
|
||||||
case MessageVerificationResult::ERR_NOT_SIGNED:
|
|
||||||
return false;
|
|
||||||
case MessageVerificationResult::OK:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static RPCHelpMan signmessagewithprivkey()
|
|
||||||
{
|
|
||||||
return RPCHelpMan{"signmessagewithprivkey",
|
|
||||||
"\nSign a message with the private key of an address\n",
|
|
||||||
{
|
|
||||||
{"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
|
|
||||||
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
|
|
||||||
},
|
|
||||||
RPCResult{
|
|
||||||
RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
|
|
||||||
},
|
|
||||||
RPCExamples{
|
|
||||||
"\nCreate the signature\n"
|
|
||||||
+ HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
|
|
||||||
"\nVerify the signature\n"
|
|
||||||
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
|
|
||||||
"\nAs a JSON-RPC call\n"
|
|
||||||
+ HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
|
|
||||||
},
|
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
|
||||||
{
|
|
||||||
std::string strPrivkey = request.params[0].get_str();
|
|
||||||
std::string strMessage = request.params[1].get_str();
|
|
||||||
|
|
||||||
CKey key = DecodeSecret(strPrivkey);
|
|
||||||
if (!key.IsValid()) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string signature;
|
|
||||||
|
|
||||||
if (!MessageSign(key, strMessage, signature)) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
return signature;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static RPCHelpMan setmocktime()
|
static RPCHelpMan setmocktime()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"setmocktime",
|
return RPCHelpMan{"setmocktime",
|
||||||
@ -795,8 +707,6 @@ void RegisterMiscRPCCommands(CRPCTable& t)
|
|||||||
{"util", &createmultisig},
|
{"util", &createmultisig},
|
||||||
{"util", &deriveaddresses},
|
{"util", &deriveaddresses},
|
||||||
{"util", &getdescriptorinfo},
|
{"util", &getdescriptorinfo},
|
||||||
{"util", &verifymessage},
|
|
||||||
{"util", &signmessagewithprivkey},
|
|
||||||
{"util", &getindexinfo},
|
{"util", &getindexinfo},
|
||||||
{"hidden", &setmocktime},
|
{"hidden", &setmocktime},
|
||||||
{"hidden", &mockscheduler},
|
{"hidden", &mockscheduler},
|
||||||
|
@ -16,6 +16,7 @@ void RegisterNetRPCCommands(CRPCTable &tableRPC);
|
|||||||
void RegisterMiscRPCCommands(CRPCTable &tableRPC);
|
void RegisterMiscRPCCommands(CRPCTable &tableRPC);
|
||||||
void RegisterMiningRPCCommands(CRPCTable &tableRPC);
|
void RegisterMiningRPCCommands(CRPCTable &tableRPC);
|
||||||
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
|
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
|
||||||
|
void RegisterSignMessageRPCCommands(CRPCTable&);
|
||||||
void RegisterSignerRPCCommands(CRPCTable &tableRPC);
|
void RegisterSignerRPCCommands(CRPCTable &tableRPC);
|
||||||
|
|
||||||
static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
|
static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
|
||||||
@ -27,6 +28,7 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
|
|||||||
RegisterMiscRPCCommands(t);
|
RegisterMiscRPCCommands(t);
|
||||||
RegisterMiningRPCCommands(t);
|
RegisterMiningRPCCommands(t);
|
||||||
RegisterRawTransactionRPCCommands(t);
|
RegisterRawTransactionRPCCommands(t);
|
||||||
|
RegisterSignMessageRPCCommands(t);
|
||||||
#ifdef ENABLE_EXTERNAL_SIGNER
|
#ifdef ENABLE_EXTERNAL_SIGNER
|
||||||
RegisterSignerRPCCommands(t);
|
RegisterSignerRPCCommands(t);
|
||||||
#endif // ENABLE_EXTERNAL_SIGNER
|
#endif // ENABLE_EXTERNAL_SIGNER
|
||||||
|
113
src/rpc/signmessage.cpp
Normal file
113
src/rpc/signmessage.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright (c) 2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <key.h>
|
||||||
|
#include <key_io.h>
|
||||||
|
#include <rpc/protocol.h>
|
||||||
|
#include <rpc/request.h>
|
||||||
|
#include <rpc/server.h>
|
||||||
|
#include <rpc/util.h>
|
||||||
|
#include <univalue.h>
|
||||||
|
#include <util/message.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
static RPCHelpMan verifymessage()
|
||||||
|
{
|
||||||
|
return RPCHelpMan{"verifymessage",
|
||||||
|
"Verify a signed message.",
|
||||||
|
{
|
||||||
|
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
|
||||||
|
{"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
|
||||||
|
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
|
||||||
|
},
|
||||||
|
RPCResult{
|
||||||
|
RPCResult::Type::BOOL, "", "If the signature is verified or not."
|
||||||
|
},
|
||||||
|
RPCExamples{
|
||||||
|
"\nUnlock the wallet for 30 seconds\n"
|
||||||
|
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
|
||||||
|
"\nCreate the signature\n"
|
||||||
|
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
|
||||||
|
"\nVerify the signature\n"
|
||||||
|
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
|
||||||
|
"\nAs a JSON-RPC call\n"
|
||||||
|
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
|
||||||
|
},
|
||||||
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
|
{
|
||||||
|
std::string strAddress = request.params[0].get_str();
|
||||||
|
std::string strSign = request.params[1].get_str();
|
||||||
|
std::string strMessage = request.params[2].get_str();
|
||||||
|
|
||||||
|
switch (MessageVerify(strAddress, strSign, strMessage)) {
|
||||||
|
case MessageVerificationResult::ERR_INVALID_ADDRESS:
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
||||||
|
case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
|
||||||
|
case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding");
|
||||||
|
case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED:
|
||||||
|
case MessageVerificationResult::ERR_NOT_SIGNED:
|
||||||
|
return false;
|
||||||
|
case MessageVerificationResult::OK:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static RPCHelpMan signmessagewithprivkey()
|
||||||
|
{
|
||||||
|
return RPCHelpMan{"signmessagewithprivkey",
|
||||||
|
"\nSign a message with the private key of an address\n",
|
||||||
|
{
|
||||||
|
{"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
|
||||||
|
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
|
||||||
|
},
|
||||||
|
RPCResult{
|
||||||
|
RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
|
||||||
|
},
|
||||||
|
RPCExamples{
|
||||||
|
"\nCreate the signature\n"
|
||||||
|
+ HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
|
||||||
|
"\nVerify the signature\n"
|
||||||
|
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
|
||||||
|
"\nAs a JSON-RPC call\n"
|
||||||
|
+ HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
|
||||||
|
},
|
||||||
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
|
{
|
||||||
|
std::string strPrivkey = request.params[0].get_str();
|
||||||
|
std::string strMessage = request.params[1].get_str();
|
||||||
|
|
||||||
|
CKey key = DecodeSecret(strPrivkey);
|
||||||
|
if (!key.IsValid()) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string signature;
|
||||||
|
|
||||||
|
if (!MessageSign(key, strMessage, signature)) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return signature;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterSignMessageRPCCommands(CRPCTable& t)
|
||||||
|
{
|
||||||
|
static const CRPCCommand commands[]{
|
||||||
|
{"util", &verifymessage},
|
||||||
|
{"util", &signmessagewithprivkey},
|
||||||
|
};
|
||||||
|
for (const auto& c : commands) {
|
||||||
|
t.appendCommand(c.name, &c);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user