aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornaughtyfox <mail.for.milo@gmail.com>2018-04-10 18:38:54 +0300
committernaughtyfox <mail.for.milo@gmail.com>2018-04-25 17:55:54 +0300
commitb21bc007049ed73a6c32cd49eb3178c6c43ad5aa (patch)
treeb7b433b625811a5fc093f40c5becbbea1e83930c
parentMerge pull request #3434 (diff)
downloadmonero-b21bc007049ed73a6c32cd49eb3178c6c43ad5aa.tar.xz
Wallet: added methods to sign and verify arbitrary message with multisig public signer's key (libwallet & wallet api)
-rw-r--r--src/wallet/api/wallet.cpp44
-rw-r--r--src/wallet/api/wallet.h2
-rw-r--r--src/wallet/api/wallet2_api.h15
-rw-r--r--src/wallet/wallet2.cpp36
-rw-r--r--src/wallet/wallet2.h16
5 files changed, 113 insertions, 0 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index b02884f67..63211fab0 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -1694,6 +1694,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);
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 4929c9673..fed1e75f2 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -157,6 +157,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);
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index d4e41c5aa..4f9d25957 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -747,6 +747,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;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 4b7e6dd93..ac8331970 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -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
{
@@ -9149,6 +9151,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
{
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index abc7bb538..4989875d4 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -964,6 +964,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);