aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorluigi1111 <luigi1111w@gmail.com>2022-09-15 00:34:05 -0500
committerluigi1111 <luigi1111w@gmail.com>2022-09-15 00:34:05 -0500
commitdf37c148d47611b173e75ae858fe51395175b21d (patch)
tree1438c6203e9f5a55bc296907d8c316e9352639a3 /src
parentMerge pull request #8554 (diff)
parentFix segfault restoring encrypted multisig seed (diff)
downloadmonero-df37c148d47611b173e75ae858fe51395175b21d.tar.xz
Merge pull request #8551
eca7f6a Fix segfault restoring encrypted multisig seed (j-berman) f713c3c Require user ack multisig is experimental to restore (j-berman) 564a7a3 multisig: fix #8537 seed restore (suggestions by @UkoeHB) (j-berman)
Diffstat (limited to 'src')
-rw-r--r--src/multisig/multisig_account.cpp9
-rw-r--r--src/multisig/multisig_account.h9
-rw-r--r--src/multisig/multisig_account_kex_impl.cpp2
-rw-r--r--src/simplewallet/simplewallet.cpp45
-rw-r--r--src/simplewallet/simplewallet.h2
-rw-r--r--src/wallet/wallet2.cpp12
-rw-r--r--src/wallet/wallet2.h3
7 files changed, 55 insertions, 27 deletions
diff --git a/src/multisig/multisig_account.cpp b/src/multisig/multisig_account.cpp
index 9bdcf2dbc..f3e78da18 100644
--- a/src/multisig/multisig_account.cpp
+++ b/src/multisig/multisig_account.cpp
@@ -127,7 +127,7 @@ namespace multisig
bool multisig_account::multisig_is_ready() const
{
if (main_kex_rounds_done())
- return m_kex_rounds_complete >= multisig_kex_rounds_required(m_signers.size(), m_threshold) + 1;
+ return m_kex_rounds_complete >= multisig_setup_rounds_required(m_signers.size(), m_threshold);
else
return false;
}
@@ -200,4 +200,11 @@ namespace multisig
return num_signers - threshold + 1;
}
//----------------------------------------------------------------------------------------------------------------------
+ // EXTERNAL
+ //----------------------------------------------------------------------------------------------------------------------
+ std::uint32_t multisig_setup_rounds_required(const std::uint32_t num_signers, const std::uint32_t threshold)
+ {
+ return multisig_kex_rounds_required(num_signers, threshold) + 1;
+ }
+ //----------------------------------------------------------------------------------------------------------------------
} //namespace multisig
diff --git a/src/multisig/multisig_account.h b/src/multisig/multisig_account.h
index 7b372bbff..7beb594b4 100644
--- a/src/multisig/multisig_account.h
+++ b/src/multisig/multisig_account.h
@@ -245,4 +245,13 @@ namespace multisig
* return: number of kex rounds required
*/
std::uint32_t multisig_kex_rounds_required(const std::uint32_t num_signers, const std::uint32_t threshold);
+
+ /**
+ * brief: multisig_setup_rounds_required - The number of setup rounds required to produce an M-of-N shared key.
+ * - A participant must complete all kex rounds and 1 initialization round.
+ * param: num_signers - number of participants in multisig (N)
+ * param: threshold - threshold of multisig (M)
+ * return: number of setup rounds required
+ */
+ std::uint32_t multisig_setup_rounds_required(const std::uint32_t num_signers, const std::uint32_t threshold);
} //namespace multisig
diff --git a/src/multisig/multisig_account_kex_impl.cpp b/src/multisig/multisig_account_kex_impl.cpp
index be9ed9cb2..443e84631 100644
--- a/src/multisig/multisig_account_kex_impl.cpp
+++ b/src/multisig/multisig_account_kex_impl.cpp
@@ -74,7 +74,7 @@ namespace multisig
"Multisig threshold may not be larger than number of signers.");
CHECK_AND_ASSERT_THROW_MES(threshold > 0, "Multisig threshold must be > 0.");
CHECK_AND_ASSERT_THROW_MES(round > 0, "Multisig kex round must be > 0.");
- CHECK_AND_ASSERT_THROW_MES(round <= multisig_kex_rounds_required(num_signers, threshold) + 1,
+ CHECK_AND_ASSERT_THROW_MES(round <= multisig_setup_rounds_required(num_signers, threshold),
"Trying to process multisig kex for an invalid round.");
}
//----------------------------------------------------------------------------------------------------------------------
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 9b63ceca6..116b5d71f 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -4118,6 +4118,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
epee::wipeable_string multisig_keys;
epee::wipeable_string password;
+ epee::wipeable_string seed_pass;
if (!handle_command_line(vm))
return false;
@@ -4134,6 +4135,17 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
if(!ask_wallet_create_if_needed()) return false;
}
+ bool enable_multisig = false;
+ if (m_restore_multisig_wallet) {
+ fail_msg_writer() << tr("Multisig is disabled.");
+ fail_msg_writer() << tr("Multisig is an experimental feature and may have bugs. Things that could go wrong include: funds sent to a multisig wallet can't be spent at all, can only be spent with the participation of a malicious group member, or can be stolen by a malicious group member.");
+ if (!command_line::is_yes(input_line("Do you want to continue restoring a multisig wallet?", true))) {
+ message_writer() << tr("You have canceled restoring a multisig wallet.");
+ return false;
+ }
+ enable_multisig = true;
+ }
+
if (!m_generate_new.empty() || m_restoring)
{
if (!m_subaddress_lookahead.empty() && !parse_subaddress_lookahead(m_subaddress_lookahead))
@@ -4213,19 +4225,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
auto pwd_container = password_prompter(tr("Enter seed offset passphrase, empty if none"), false);
if (std::cin.eof() || !pwd_container)
return false;
- epee::wipeable_string seed_pass = pwd_container->password();
- if (!seed_pass.empty())
- {
- if (m_restore_multisig_wallet)
- {
- crypto::secret_key key;
- crypto::cn_slow_hash(seed_pass.data(), seed_pass.size(), (crypto::hash&)key);
- sc_reduce32((unsigned char*)key.data);
- multisig_keys = m_wallet->decrypt<epee::wipeable_string>(std::string(multisig_keys.data(), multisig_keys.size()), key, true);
- }
- else
- m_recovery_key = cryptonote::decrypt_key(m_recovery_key, seed_pass);
- }
+ seed_pass = pwd_container->password();
+ if (!seed_pass.empty() && !m_restore_multisig_wallet)
+ m_recovery_key = cryptonote::decrypt_key(m_recovery_key, seed_pass);
}
if (!m_generate_from_view_key.empty())
{
@@ -4568,7 +4570,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
m_wallet_file = m_generate_new;
boost::optional<epee::wipeable_string> r;
if (m_restore_multisig_wallet)
- r = new_wallet(vm, multisig_keys, old_language);
+ r = new_wallet(vm, multisig_keys, seed_pass, old_language);
else
r = new_wallet(vm, m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic, old_language);
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
@@ -4667,6 +4669,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
m_wallet->set_refresh_from_block_height(m_restore_height);
}
+ if (enable_multisig)
+ m_wallet->enable_multisig(true);
m_wallet->rewrite(m_wallet_file, password);
}
else
@@ -5057,7 +5061,7 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
}
//----------------------------------------------------------------------------------------------------
boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
- const epee::wipeable_string &multisig_keys, const std::string &old_language)
+ const epee::wipeable_string &multisig_keys, const epee::wipeable_string &seed_pass, const std::string &old_language)
{
std::pair<std::unique_ptr<tools::wallet2>, tools::password_container> rc;
try { rc = tools::wallet2::make_new(vm, false, password_prompter); }
@@ -5091,7 +5095,16 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
try
{
- m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys, create_address_file);
+ if (seed_pass.empty())
+ m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys, create_address_file);
+ else
+ {
+ crypto::secret_key key;
+ crypto::cn_slow_hash(seed_pass.data(), seed_pass.size(), (crypto::hash&)key);
+ sc_reduce32((unsigned char*)key.data);
+ const epee::wipeable_string &msig_keys = m_wallet->decrypt<epee::wipeable_string>(std::string(multisig_keys.data(), multisig_keys.size()), key, true);
+ m_wallet->generate(m_wallet_file, std::move(rc.second).password(), msig_keys, create_address_file);
+ }
bool ready;
uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total) || !ready)
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 6a9fa149d..b18fa2dd6 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -101,7 +101,7 @@ namespace cryptonote
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const cryptonote::account_public_address& address,
const boost::optional<crypto::secret_key>& spendkey, const crypto::secret_key& viewkey);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm,
- const epee::wipeable_string &multisig_keys, const std::string &old_language);
+ const epee::wipeable_string &multisig_keys, const epee::wipeable_string &seed_pass, const std::string &old_language);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm);
boost::optional<epee::wipeable_string> open_wallet(const boost::program_options::variables_map& vm);
bool close_wallet();
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index b6d95b6b7..6ebb21924 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -4691,7 +4691,8 @@ void wallet2::init_type(hw::device::device_type device_type)
}
/*!
- * \brief Generates a wallet or restores one.
+ * \brief Generates a wallet or restores one. Assumes the multisig setup
+ * has already completed for the provided multisig info.
* \param wallet_ Name of wallet file
* \param password Password of wallet file
* \param multisig_data The multisig restore info and keys
@@ -4750,11 +4751,6 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
crypto::public_key local_signer;
THROW_WALLET_EXCEPTION_IF(!crypto::secret_key_to_public_key(spend_secret_key, local_signer), error::invalid_multisig_seed);
THROW_WALLET_EXCEPTION_IF(std::find(multisig_signers.begin(), multisig_signers.end(), local_signer) == multisig_signers.end(), error::invalid_multisig_seed);
- rct::key skey = rct::zero();
- for (const auto &msk: multisig_keys)
- sc_add(skey.bytes, skey.bytes, rct::sk2rct(msk).bytes);
- THROW_WALLET_EXCEPTION_IF(!(rct::rct2sk(skey) == spend_secret_key), error::invalid_multisig_seed);
- memwipe(&skey, sizeof(rct::key));
m_account.make_multisig(view_secret_key, spend_secret_key, spend_public_key, multisig_keys);
@@ -4765,6 +4761,8 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = true;
m_multisig_threshold = threshold;
m_multisig_signers = multisig_signers;
+ // wallet is assumed already finalized
+ m_multisig_rounds_passed = multisig::multisig_setup_rounds_required(m_multisig_signers.size(), m_multisig_threshold);
setup_keys(password);
create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
@@ -5215,7 +5213,7 @@ bool wallet2::multisig(bool *ready, uint32_t *threshold, uint32_t *total) const
if (ready)
{
*ready = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity())) &&
- (m_multisig_rounds_passed == multisig::multisig_kex_rounds_required(m_multisig_signers.size(), m_multisig_threshold) + 1);
+ (m_multisig_rounds_passed == multisig::multisig_setup_rounds_required(m_multisig_signers.size(), m_multisig_threshold));
}
return true;
}
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 1f84458a6..38b3b2e72 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -817,7 +817,8 @@ private:
};
/*!
- * \brief Generates a wallet or restores one.
+ * \brief Generates a wallet or restores one. Assumes the multisig setup
+ * has already completed for the provided multisig info.
* \param wallet_ Name of wallet file
* \param password Password of wallet file
* \param multisig_data The multisig restore info and keys