mirror of
https://codeberg.org/anoncontributorxmr/monero.git
synced 2024-12-29 00:27:52 +00:00
Merge pull request #3598
b21bc00
Wallet: added methods to sign and verify arbitrary message with multisig public signer's key (libwallet & wallet api) (naughtyfox)
This commit is contained in:
commit
00635bd68b
5 changed files with 113 additions and 0 deletions
|
@ -1766,6 +1766,50 @@ bool WalletImpl::verifySignedMessage(const std::string &message, const std::stri
|
|||
return m_wallet->verify(message, info.address, signature);
|
||||
}
|
||||
|
||||
std::string WalletImpl::signMultisigParticipant(const std::string &message) const
|
||||
{
|
||||
clearStatus();
|
||||
|
||||
bool ready = false;
|
||||
if (!m_wallet->multisig(&ready) || !ready) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = tr("The wallet must be in multisig ready state");
|
||||
return {};
|
||||
}
|
||||
|
||||
try {
|
||||
return m_wallet->sign_multisig_participant(message);
|
||||
} catch (const std::exception& e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool WalletImpl::verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const
|
||||
{
|
||||
clearStatus();
|
||||
|
||||
cryptonote::blobdata pkeyData;
|
||||
if(!epee::string_tools::parse_hexstr_to_binbuff(publicKey, pkeyData) || pkeyData.size() != sizeof(crypto::public_key))
|
||||
{
|
||||
m_status = Status_Error;
|
||||
m_errorString = tr("Given string is not a key");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
crypto::public_key pkey = *reinterpret_cast<const crypto::public_key*>(pkeyData.data());
|
||||
return m_wallet->verify_with_public_key(message, pkey, signature);
|
||||
} catch (const std::exception& e) {
|
||||
m_status = Status_Error;
|
||||
m_errorString = e.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WalletImpl::connectToDaemon()
|
||||
{
|
||||
bool result = m_wallet->check_connection(NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS);
|
||||
|
|
|
@ -166,6 +166,8 @@ public:
|
|||
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const;
|
||||
virtual std::string signMessage(const std::string &message);
|
||||
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const;
|
||||
virtual std::string signMultisigParticipant(const std::string &message) const;
|
||||
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const;
|
||||
virtual void startRefresh();
|
||||
virtual void pauseRefresh();
|
||||
virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error);
|
||||
|
|
|
@ -825,6 +825,21 @@ struct Wallet
|
|||
*/
|
||||
virtual bool verifySignedMessage(const std::string &message, const std::string &addres, const std::string &signature) const = 0;
|
||||
|
||||
/*!
|
||||
* \brief signMultisigParticipant signs given message with the multisig public signer key
|
||||
* \param message message to sign
|
||||
* \return signature in case of success. Sets status to Error and return empty string in case of error
|
||||
*/
|
||||
virtual std::string signMultisigParticipant(const std::string &message) const = 0;
|
||||
/*!
|
||||
* \brief verifyMessageWithPublicKey verifies that message was signed with the given public key
|
||||
* \param message message
|
||||
* \param publicKey hex encoded public key
|
||||
* \param signature signature of the message
|
||||
* \return true if the signature is correct. false and sets error state in case of error
|
||||
*/
|
||||
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const = 0;
|
||||
|
||||
virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) = 0;
|
||||
|
||||
virtual std::string getDefaultDataDir() const = 0;
|
||||
|
|
|
@ -115,6 +115,8 @@ using namespace cryptonote;
|
|||
#define STAGENET_SEGREGATION_FORK_HEIGHT 1000000
|
||||
#define SEGREGATION_FORK_VICINITY 1500 /* blocks */
|
||||
|
||||
static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -9282,6 +9284,40 @@ bool wallet2::verify(const std::string &data, const cryptonote::account_public_a
|
|||
memcpy(&s, decoded.data(), sizeof(s));
|
||||
return crypto::check_signature(hash, address.m_spend_public_key, s);
|
||||
}
|
||||
|
||||
std::string wallet2::sign_multisig_participant(const std::string& data) const
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
|
||||
|
||||
crypto::hash hash;
|
||||
crypto::cn_fast_hash(data.data(), data.size(), hash);
|
||||
const cryptonote::account_keys &keys = m_account.get_keys();
|
||||
crypto::signature signature;
|
||||
crypto::generate_signature(hash, get_multisig_signer_public_key(), keys.m_spend_secret_key, signature);
|
||||
return MULTISIG_SIGNATURE_MAGIC + tools::base58::encode(std::string((const char *)&signature, sizeof(signature)));
|
||||
}
|
||||
|
||||
bool wallet2::verify_with_public_key(const std::string &data, const crypto::public_key &public_key, const std::string &signature) const
|
||||
{
|
||||
if (signature.size() < MULTISIG_SIGNATURE_MAGIC.size() || signature.substr(0, MULTISIG_SIGNATURE_MAGIC.size()) != MULTISIG_SIGNATURE_MAGIC) {
|
||||
MERROR("Signature header check error");
|
||||
return false;
|
||||
}
|
||||
crypto::hash hash;
|
||||
crypto::cn_fast_hash(data.data(), data.size(), hash);
|
||||
std::string decoded;
|
||||
if (!tools::base58::decode(signature.substr(MULTISIG_SIGNATURE_MAGIC.size()), decoded)) {
|
||||
MERROR("Signature decoding error");
|
||||
return false;
|
||||
}
|
||||
crypto::signature s;
|
||||
if (sizeof(s) != decoded.size()) {
|
||||
MERROR("Signature decoding error");
|
||||
return false;
|
||||
}
|
||||
memcpy(&s, decoded.data(), sizeof(s));
|
||||
return crypto::check_signature(hash, public_key, s);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const
|
||||
{
|
||||
|
|
|
@ -969,6 +969,22 @@ namespace tools
|
|||
std::string sign(const std::string &data) const;
|
||||
bool verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const;
|
||||
|
||||
/*!
|
||||
* \brief sign_multisig_participant signs given message with the multisig public signer key
|
||||
* \param data message to sign
|
||||
* \throws if wallet is not multisig
|
||||
* \return signature
|
||||
*/
|
||||
std::string sign_multisig_participant(const std::string& data) const;
|
||||
/*!
|
||||
* \brief verify_with_public_key verifies message was signed with given public key
|
||||
* \param data message
|
||||
* \param public_key public key to check signature
|
||||
* \param signature signature of the message
|
||||
* \return true if the signature is correct
|
||||
*/
|
||||
bool verify_with_public_key(const std::string &data, const crypto::public_key &public_key, const std::string &signature) const;
|
||||
|
||||
// Import/Export wallet data
|
||||
std::vector<tools::wallet2::transfer_details> export_outputs() const;
|
||||
size_t import_outputs(const std::vector<tools::wallet2::transfer_details> &outputs);
|
||||
|
|
Loading…
Reference in a new issue