mirror of
				https://git.wownero.com/wownero/wownero.git
				synced 2024-08-15 01:03:23 +00:00 
			
		
		
		
	Merge pull request #8545
12e7c41Merge pull request #5 from j-berman/restore-msig-encrypted-seed (Justin Berman)848a0c0Fix segfault restoring encrypted multisig seed (j-berman)401f5d9Require user ack multisig is experimental to restore (j-berman)fc8a5d6multisig: fix #8537 seed restore (suggestions by @UkoeHB) (j-berman)
This commit is contained in:
		
						commit
						7cbae6ca98
					
				
					 8 changed files with 56 additions and 28 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.");
 | 
			
		||||
  }
 | 
			
		||||
  //----------------------------------------------------------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4116,6 +4116,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -4132,6 +4133,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))
 | 
			
		||||
| 
						 | 
				
			
			@ -4211,19 +4223,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())
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -4566,7 +4568,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"));
 | 
			
		||||
| 
						 | 
				
			
			@ -4665,6 +4667,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
 | 
			
		||||
| 
						 | 
				
			
			@ -5062,7 +5066,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); }
 | 
			
		||||
| 
						 | 
				
			
			@ -5096,7 +5100,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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4737,7 +4737,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
 | 
			
		||||
| 
						 | 
				
			
			@ -4796,11 +4797,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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4811,6 +4807,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -5261,7 +5259,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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -171,7 +171,7 @@ static void make_wallets(std::vector<tools::wallet2>& wallets, unsigned int M)
 | 
			
		|||
{
 | 
			
		||||
  ASSERT_TRUE(wallets.size() > 1 && wallets.size() <= KEYS_COUNT);
 | 
			
		||||
  ASSERT_TRUE(M <= wallets.size());
 | 
			
		||||
  std::uint32_t total_rounds_required = multisig::multisig_kex_rounds_required(wallets.size(), M) + 1;
 | 
			
		||||
  std::uint32_t total_rounds_required = multisig::multisig_setup_rounds_required(wallets.size(), M);
 | 
			
		||||
  std::uint32_t rounds_complete{0};
 | 
			
		||||
 | 
			
		||||
  // initialize wallets, get first round multisig kex msgs
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue