Navigation Menu

Skip to content

Commit

Permalink
Verify and sign arbitrary message with multisig public signer's key i…
Browse files Browse the repository at this point in the history
…n libwallet & wallet api
  • Loading branch information
miltonf committed Mar 2, 2019
1 parent 08de03f commit 5d43c46
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/wallet/api/wallet.cpp
Expand Up @@ -1775,6 +1775,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);
Expand Down
2 changes: 2 additions & 0 deletions src/wallet/api/wallet.h
Expand Up @@ -167,6 +167,8 @@ class WalletImpl : public Wallet
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);
Expand Down
15 changes: 15 additions & 0 deletions src/wallet/api/wallet2_api.h
Expand Up @@ -830,6 +830,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;
Expand Down
35 changes: 35 additions & 0 deletions src/wallet/wallet2.cpp
Expand Up @@ -115,6 +115,7 @@ using namespace cryptonote;
#define STAGENET_SEGREGATION_FORK_HEIGHT 1000000
#define SEGREGATION_FORK_VICINITY 1500 /* blocks */

static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";

namespace
{
Expand Down Expand Up @@ -9313,6 +9314,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
{
Expand Down
16 changes: 16 additions & 0 deletions src/wallet/wallet2.h
Expand Up @@ -967,6 +967,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);
Expand Down

0 comments on commit 5d43c46

Please sign in to comment.