mirror of
				https://git.wownero.com/wownero/wownero.git
				synced 2024-08-15 01:03:23 +00:00 
			
		
		
		
	wallet2: fix store_to() and change_password()
				
					
				
			Resolves #8932 and: 2. Not storing cache when new path is different from old in `store_to()` and 3. Detecting same path when new path contains entire string of old path in `store_to()` and 4. Changing your password / decrypting your keys (in this method or others) and providing a bad original password and getting no error and 5. Changing your password and storing to a new file
This commit is contained in:
		
							parent
							
								
									eac1b86bb2
								
							
						
					
					
						commit
						ba98269ca5
					
				
					 7 changed files with 359 additions and 42 deletions
				
			
		| 
						 | 
				
			
			@ -1003,6 +1003,24 @@ uint64_t num_priv_multisig_keys_post_setup(uint64_t threshold, uint64_t total)
 | 
			
		|||
  return n_multisig_keys;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Derives the chacha key to encrypt wallet cache files given the chacha key to encrypt the wallet keys files
 | 
			
		||||
 *
 | 
			
		||||
 * @param keys_data_key the chacha key that encrypts wallet keys files
 | 
			
		||||
 * @return crypto::chacha_key the chacha key that encrypts the wallet cache files
 | 
			
		||||
 */
 | 
			
		||||
crypto::chacha_key derive_cache_key(const crypto::chacha_key& keys_data_key)
 | 
			
		||||
{
 | 
			
		||||
  static_assert(HASH_SIZE == sizeof(crypto::chacha_key), "Mismatched sizes of hash and chacha key");
 | 
			
		||||
 | 
			
		||||
  crypto::chacha_key cache_key;
 | 
			
		||||
  epee::mlocked<tools::scrubbed_arr<char, HASH_SIZE+1>> cache_key_data;
 | 
			
		||||
  memcpy(cache_key_data.data(), &keys_data_key, HASH_SIZE);
 | 
			
		||||
  cache_key_data[HASH_SIZE] = config::HASH_KEY_WALLET_CACHE;
 | 
			
		||||
  cn_fast_hash(cache_key_data.data(), HASH_SIZE+1, (crypto::hash&) cache_key);
 | 
			
		||||
 | 
			
		||||
  return cache_key;
 | 
			
		||||
}
 | 
			
		||||
  //-----------------------------------------------------------------
 | 
			
		||||
} //namespace
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4406,6 +4424,10 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
 | 
			
		|||
  crypto::chacha_key key;
 | 
			
		||||
  crypto::generate_chacha_key(password.data(), password.size(), key, m_kdf_rounds);
 | 
			
		||||
 | 
			
		||||
  // We use m_cache_key as a deterministic test to see if given key corresponds to original password
 | 
			
		||||
  const crypto::chacha_key cache_key = derive_cache_key(key);
 | 
			
		||||
  THROW_WALLET_EXCEPTION_IF(cache_key != m_cache_key, error::invalid_password);
 | 
			
		||||
 | 
			
		||||
  if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
 | 
			
		||||
  {
 | 
			
		||||
    account.encrypt_viewkey(key);
 | 
			
		||||
| 
						 | 
				
			
			@ -4630,11 +4652,8 @@ void wallet2::setup_keys(const epee::wipeable_string &password)
 | 
			
		|||
    m_account.decrypt_viewkey(key);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static_assert(HASH_SIZE == sizeof(crypto::chacha_key), "Mismatched sizes of hash and chacha key");
 | 
			
		||||
  epee::mlocked<tools::scrubbed_arr<char, HASH_SIZE+1>> cache_key_data;
 | 
			
		||||
  memcpy(cache_key_data.data(), &key, HASH_SIZE);
 | 
			
		||||
  cache_key_data[HASH_SIZE] = config::HASH_KEY_WALLET_CACHE;
 | 
			
		||||
  cn_fast_hash(cache_key_data.data(), HASH_SIZE+1, (crypto::hash&)m_cache_key);
 | 
			
		||||
  m_cache_key = derive_cache_key(key);
 | 
			
		||||
 | 
			
		||||
  get_ringdb_key();
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			@ -4643,9 +4662,8 @@ void wallet2::change_password(const std::string &filename, const epee::wipeable_
 | 
			
		|||
  if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
 | 
			
		||||
    decrypt_keys(original_password);
 | 
			
		||||
  setup_keys(new_password);
 | 
			
		||||
  rewrite(filename, new_password);
 | 
			
		||||
  if (!filename.empty())
 | 
			
		||||
    store();
 | 
			
		||||
    store_to(filename, new_password, true); // force rewrite keys file to possible new location
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
/*!
 | 
			
		||||
| 
						 | 
				
			
			@ -5151,6 +5169,10 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key)
 | 
			
		|||
 | 
			
		||||
void wallet2::decrypt_keys(const crypto::chacha_key &key)
 | 
			
		||||
{
 | 
			
		||||
  // We use m_cache_key as a deterministic test to see if given key corresponds to original password
 | 
			
		||||
  const crypto::chacha_key cache_key = derive_cache_key(key);
 | 
			
		||||
  THROW_WALLET_EXCEPTION_IF(cache_key != m_cache_key, error::invalid_password);
 | 
			
		||||
 | 
			
		||||
  m_account.encrypt_viewkey(key);
 | 
			
		||||
  m_account.decrypt_keys(key);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6311,22 +6333,32 @@ void wallet2::store()
 | 
			
		|||
    store_to("", epee::wipeable_string());
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
void wallet2::store_to(const std::string &path, const epee::wipeable_string &password)
 | 
			
		||||
void wallet2::store_to(const std::string &path, const epee::wipeable_string &password, bool force_rewrite_keys)
 | 
			
		||||
{
 | 
			
		||||
  trim_hashchain();
 | 
			
		||||
 | 
			
		||||
  const bool had_old_wallet_files = !m_wallet_file.empty();
 | 
			
		||||
  THROW_WALLET_EXCEPTION_IF(!had_old_wallet_files && path.empty(), error::wallet_internal_error,
 | 
			
		||||
    "Cannot resave wallet to current file since wallet was not loaded from file to begin with");
 | 
			
		||||
 | 
			
		||||
  // if file is the same, we do:
 | 
			
		||||
  // 1. save wallet to the *.new file
 | 
			
		||||
  // 2. remove old wallet file
 | 
			
		||||
  // 3. rename *.new to wallet_name
 | 
			
		||||
  // 1. overwrite the keys file iff force_rewrite_keys is specified
 | 
			
		||||
  // 2. save cache to the *.new file
 | 
			
		||||
  // 3. rename *.new to wallet_name, replacing old cache file
 | 
			
		||||
  // else we do:
 | 
			
		||||
  // 1. prepare new file names with "path" variable
 | 
			
		||||
  // 2. store new keys files
 | 
			
		||||
  // 3. remove old keys file
 | 
			
		||||
  // 4. store new cache file
 | 
			
		||||
  // 5. remove old cache file
 | 
			
		||||
 | 
			
		||||
  // handle if we want just store wallet state to current files (ex store() replacement);
 | 
			
		||||
  bool same_file = true;
 | 
			
		||||
  if (!path.empty())
 | 
			
		||||
  bool same_file = had_old_wallet_files && path.empty();
 | 
			
		||||
  if (had_old_wallet_files && !path.empty())
 | 
			
		||||
  {
 | 
			
		||||
    std::string canonical_path = boost::filesystem::canonical(m_wallet_file).string();
 | 
			
		||||
    size_t pos = canonical_path.find(path);
 | 
			
		||||
    same_file = pos != std::string::npos;
 | 
			
		||||
    const std::string canonical_old_path = boost::filesystem::canonical(m_wallet_file).string();
 | 
			
		||||
    const std::string canonical_new_path = boost::filesystem::weakly_canonical(path).string();
 | 
			
		||||
    same_file = canonical_old_path == canonical_new_path;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6347,7 +6379,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  // get wallet cache data
 | 
			
		||||
  boost::optional<wallet2::cache_file_data> cache_file_data = get_cache_file_data(password);
 | 
			
		||||
  boost::optional<wallet2::cache_file_data> cache_file_data = get_cache_file_data();
 | 
			
		||||
  THROW_WALLET_EXCEPTION_IF(cache_file_data == boost::none, error::wallet_internal_error, "failed to generate wallet cache data");
 | 
			
		||||
 | 
			
		||||
  const std::string new_file = same_file ? m_wallet_file + ".new" : path;
 | 
			
		||||
| 
						 | 
				
			
			@ -6356,12 +6388,20 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
 | 
			
		|||
  const std::string old_address_file = m_wallet_file + ".address.txt";
 | 
			
		||||
  const std::string old_mms_file = m_mms_file;
 | 
			
		||||
 | 
			
		||||
  // save keys to the new file
 | 
			
		||||
  // if we here, main wallet file is saved and we only need to save keys and address files
 | 
			
		||||
  if (!same_file) {
 | 
			
		||||
  if (!same_file)
 | 
			
		||||
  {
 | 
			
		||||
    prepare_file_names(path);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!same_file || force_rewrite_keys)
 | 
			
		||||
  {
 | 
			
		||||
    bool r = store_keys(m_keys_file, password, false);
 | 
			
		||||
    THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!same_file && had_old_wallet_files)
 | 
			
		||||
  {
 | 
			
		||||
    bool r = false;
 | 
			
		||||
    if (boost::filesystem::exists(old_address_file))
 | 
			
		||||
    {
 | 
			
		||||
      // save address to the new file
 | 
			
		||||
| 
						 | 
				
			
			@ -6374,11 +6414,6 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
 | 
			
		|||
        LOG_ERROR("error removing file: " << old_address_file);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // remove old wallet file
 | 
			
		||||
    r = boost::filesystem::remove(old_file);
 | 
			
		||||
    if (!r) {
 | 
			
		||||
      LOG_ERROR("error removing file: " << old_file);
 | 
			
		||||
    }
 | 
			
		||||
    // remove old keys file
 | 
			
		||||
    r = boost::filesystem::remove(old_keys_file);
 | 
			
		||||
    if (!r) {
 | 
			
		||||
| 
						 | 
				
			
			@ -6392,8 +6427,9 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
 | 
			
		|||
        LOG_ERROR("error removing file: " << old_mms_file);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    // save to new file
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Save cache to new file. If storing to the same file, the temp path has the ".new" extension
 | 
			
		||||
#ifdef WIN32
 | 
			
		||||
    // On Windows avoid using std::ofstream which does not work with UTF-8 filenames
 | 
			
		||||
    // The price to pay is temporary higher memory consumption for string stream + binary archive
 | 
			
		||||
| 
						 | 
				
			
			@ -6413,10 +6449,20 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
 | 
			
		|||
    THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (same_file)
 | 
			
		||||
  {
 | 
			
		||||
    // here we have "*.new" file, we need to rename it to be without ".new"
 | 
			
		||||
    std::error_code e = tools::replace_file(new_file, m_wallet_file);
 | 
			
		||||
    THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e);
 | 
			
		||||
  }
 | 
			
		||||
  else if (!same_file && had_old_wallet_files)
 | 
			
		||||
  {
 | 
			
		||||
    // remove old wallet file
 | 
			
		||||
    bool r = boost::filesystem::remove(old_file);
 | 
			
		||||
    if (!r) {
 | 
			
		||||
      LOG_ERROR("error removing file: " << old_file);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (m_message_store.get_active())
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -6426,7 +6472,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data(const epee::wipeable_string &passwords)
 | 
			
		||||
boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
 | 
			
		||||
{
 | 
			
		||||
  trim_hashchain();
 | 
			
		||||
  try
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -940,22 +940,32 @@ private:
 | 
			
		|||
    /*!
 | 
			
		||||
     * \brief store_to  Stores wallet to another file(s), deleting old ones
 | 
			
		||||
     * \param path      Path to the wallet file (keys and address filenames will be generated based on this filename)
 | 
			
		||||
     * \param password  Password to protect new wallet (TODO: probably better save the password in the wallet object?)
 | 
			
		||||
     * \param password  Password that currently locks the wallet
 | 
			
		||||
     * \param force_rewrite_keys if true, always rewrite keys file
 | 
			
		||||
     *
 | 
			
		||||
     * Leave both "path" and "password" blank to restore the cache file to the current position in the disk
 | 
			
		||||
     * (which is the same as calling `store()`). If you want to store the wallet with a new password,
 | 
			
		||||
     * use the method `change_password()`.
 | 
			
		||||
     *
 | 
			
		||||
     * Normally the keys file is not overwritten when storing, except when force_rewrite_keys is true
 | 
			
		||||
     * or when `path` is a new wallet file.
 | 
			
		||||
     *
 | 
			
		||||
     * \throw error::invalid_password If storing keys file and old password is incorrect
 | 
			
		||||
     */
 | 
			
		||||
    void store_to(const std::string &path, const epee::wipeable_string &password);
 | 
			
		||||
    void store_to(const std::string &path, const epee::wipeable_string &password, bool force_rewrite_keys = false);
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief get_keys_file_data  Get wallet keys data which can be stored to a wallet file.
 | 
			
		||||
     * \param password            Password of the encrypted wallet buffer (TODO: probably better save the password in the wallet object?)
 | 
			
		||||
     * \param password            Password that currently locks the wallet
 | 
			
		||||
     * \param watch_only          true to include only view key, false to include both spend and view keys
 | 
			
		||||
     * \return                    Encrypted wallet keys data which can be stored to a wallet file
 | 
			
		||||
     * \throw                     error::invalid_password if password does not match current wallet
 | 
			
		||||
     */
 | 
			
		||||
    boost::optional<wallet2::keys_file_data> get_keys_file_data(const epee::wipeable_string& password, bool watch_only);
 | 
			
		||||
    /*!
 | 
			
		||||
     * \brief get_cache_file_data   Get wallet cache data which can be stored to a wallet file.
 | 
			
		||||
     * \param password              Password to protect the wallet cache data (TODO: probably better save the password in the wallet object?)
 | 
			
		||||
     * \return                      Encrypted wallet cache data which can be stored to a wallet file
 | 
			
		||||
     * \return                      Encrypted wallet cache data which can be stored to a wallet file (using current password)
 | 
			
		||||
     */
 | 
			
		||||
    boost::optional<wallet2::cache_file_data> get_cache_file_data(const epee::wipeable_string& password);
 | 
			
		||||
    boost::optional<wallet2::cache_file_data> get_cache_file_data();
 | 
			
		||||
 | 
			
		||||
    std::string path() const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,14 +72,8 @@ else ()
 | 
			
		|||
  include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest/include")
 | 
			
		||||
endif (GTest_FOUND)
 | 
			
		||||
 | 
			
		||||
file(COPY
 | 
			
		||||
  data/wallet_9svHk1.keys
 | 
			
		||||
  data/wallet_9svHk1
 | 
			
		||||
  data/outputs
 | 
			
		||||
  data/unsigned_monero_tx
 | 
			
		||||
  data/signed_monero_tx
 | 
			
		||||
  data/sha256sum
 | 
			
		||||
  DESTINATION data)
 | 
			
		||||
message(STATUS "Copying test data directory...")
 | 
			
		||||
file(COPY data DESTINATION .) # Copy data directory from source root to build root
 | 
			
		||||
 | 
			
		||||
if (CMAKE_BUILD_TYPE STREQUAL "fuzz" OR OSSFUZZ)
 | 
			
		||||
  add_subdirectory(fuzz)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								tests/data/wallet_00fd416a
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wallet_00fd416a
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tests/data/wallet_00fd416a.keys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/data/wallet_00fd416a.keys
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -97,6 +97,7 @@ set(unit_tests_sources
 | 
			
		|||
  output_selection.cpp
 | 
			
		||||
  vercmp.cpp
 | 
			
		||||
  ringdb.cpp
 | 
			
		||||
  wallet_storage.cpp
 | 
			
		||||
  wipeable_string.cpp
 | 
			
		||||
  is_hdd.cpp
 | 
			
		||||
  aligned.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										266
									
								
								tests/unit_tests/wallet_storage.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								tests/unit_tests/wallet_storage.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,266 @@
 | 
			
		|||
// Copyright (c) 2023, The Monero Project
 | 
			
		||||
//
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without modification, are
 | 
			
		||||
// permitted provided that the following conditions are met:
 | 
			
		||||
//
 | 
			
		||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
 | 
			
		||||
//    conditions and the following disclaimer.
 | 
			
		||||
//
 | 
			
		||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
 | 
			
		||||
//    of conditions and the following disclaimer in the documentation and/or other
 | 
			
		||||
//    materials provided with the distribution.
 | 
			
		||||
//
 | 
			
		||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
 | 
			
		||||
//    used to endorse or promote products derived from this software without specific
 | 
			
		||||
//    prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 | 
			
		||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 | 
			
		||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 | 
			
		||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
#include "unit_tests_utils.h"
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
 | 
			
		||||
#include "file_io_utils.h"
 | 
			
		||||
#include "wallet/wallet2.h"
 | 
			
		||||
 | 
			
		||||
using namespace boost::filesystem;
 | 
			
		||||
using namespace epee::file_io_utils;
 | 
			
		||||
 | 
			
		||||
static constexpr const char WALLET_00fd416a_PRIMARY_ADDRESS[] =
 | 
			
		||||
    "45p2SngJAPSJbqSiUvYfS3BfhEdxZmv8pDt25oW1LzxrZv9Uq6ARagiFViMGUE3gJk5VPWingCXVf1p2tyAy6SUeSHPhbve";
 | 
			
		||||
 | 
			
		||||
TEST(wallet_storage, store_to_file2file)
 | 
			
		||||
{
 | 
			
		||||
    const path source_wallet_file = unit_test::data_dir / "wallet_00fd416a";
 | 
			
		||||
    const path interm_wallet_file = unit_test::data_dir / "wallet_00fd416a_copy_file2file";
 | 
			
		||||
    const path target_wallet_file = unit_test::data_dir / "wallet_00fd416a_new_file2file";
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(source_wallet_file.string()));
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(source_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    copy_file(source_wallet_file, interm_wallet_file, copy_option::overwrite_if_exists);
 | 
			
		||||
    copy_file(source_wallet_file.string() + ".keys", interm_wallet_file.string() + ".keys", copy_option::overwrite_if_exists);
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(interm_wallet_file.string()));
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(interm_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string()))
 | 
			
		||||
        remove(target_wallet_file);
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string() + ".keys"))
 | 
			
		||||
        remove(target_wallet_file.string() + ".keys");
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    epee::wipeable_string password("beepbeep");
 | 
			
		||||
 | 
			
		||||
    const auto files_are_expected = [&]()
 | 
			
		||||
    {
 | 
			
		||||
        EXPECT_FALSE(is_file_exist(interm_wallet_file.string()));
 | 
			
		||||
        EXPECT_FALSE(is_file_exist(interm_wallet_file.string() + ".keys"));
 | 
			
		||||
        EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
        EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(interm_wallet_file.string(), password);
 | 
			
		||||
        const std::string primary_address = w.get_address_as_str();
 | 
			
		||||
        EXPECT_EQ(WALLET_00fd416a_PRIMARY_ADDRESS, primary_address);
 | 
			
		||||
        w.store_to(target_wallet_file.string(), password);
 | 
			
		||||
        files_are_expected();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    files_are_expected();
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(target_wallet_file.string(), password);
 | 
			
		||||
        const std::string primary_address = w.get_address_as_str();
 | 
			
		||||
        EXPECT_EQ(WALLET_00fd416a_PRIMARY_ADDRESS, primary_address);
 | 
			
		||||
        w.store_to("", "");
 | 
			
		||||
        files_are_expected();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    files_are_expected();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(wallet_storage, store_to_mem2file)
 | 
			
		||||
{
 | 
			
		||||
    const path target_wallet_file = unit_test::data_dir / "wallet_mem2file";
 | 
			
		||||
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string()))
 | 
			
		||||
        remove(target_wallet_file);
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string() + ".keys"))
 | 
			
		||||
        remove(target_wallet_file.string() + ".keys");
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    epee::wipeable_string password("beepbeep2");
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.generate("", password);
 | 
			
		||||
        w.store_to(target_wallet_file.string(), password);
 | 
			
		||||
 | 
			
		||||
        EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
        EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(target_wallet_file.string(), password);
 | 
			
		||||
 | 
			
		||||
        EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
        EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(wallet_storage, change_password_same_file)
 | 
			
		||||
{
 | 
			
		||||
    const path source_wallet_file = unit_test::data_dir / "wallet_00fd416a";
 | 
			
		||||
    const path interm_wallet_file = unit_test::data_dir / "wallet_00fd416a_copy_change_password_same";
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(source_wallet_file.string()));
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(source_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    copy_file(source_wallet_file, interm_wallet_file, copy_option::overwrite_if_exists);
 | 
			
		||||
    copy_file(source_wallet_file.string() + ".keys", interm_wallet_file.string() + ".keys", copy_option::overwrite_if_exists);
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(interm_wallet_file.string()));
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(interm_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    epee::wipeable_string old_password("beepbeep");
 | 
			
		||||
    epee::wipeable_string new_password("meepmeep");
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(interm_wallet_file.string(), old_password);
 | 
			
		||||
        const std::string primary_address = w.get_address_as_str();
 | 
			
		||||
        EXPECT_EQ(WALLET_00fd416a_PRIMARY_ADDRESS, primary_address);
 | 
			
		||||
        w.change_password(w.get_wallet_file(), old_password, new_password);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(interm_wallet_file.string(), new_password);
 | 
			
		||||
        const std::string primary_address = w.get_address_as_str();
 | 
			
		||||
        EXPECT_EQ(WALLET_00fd416a_PRIMARY_ADDRESS, primary_address);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        EXPECT_THROW(w.load(interm_wallet_file.string(), old_password), tools::error::invalid_password);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(wallet_storage, change_password_different_file)
 | 
			
		||||
{
 | 
			
		||||
    const path source_wallet_file = unit_test::data_dir / "wallet_00fd416a";
 | 
			
		||||
    const path interm_wallet_file = unit_test::data_dir / "wallet_00fd416a_copy_change_password_diff";
 | 
			
		||||
    const path target_wallet_file = unit_test::data_dir / "wallet_00fd416a_new_change_password_diff";
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(source_wallet_file.string()));
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(source_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    copy_file(source_wallet_file, interm_wallet_file, copy_option::overwrite_if_exists);
 | 
			
		||||
    copy_file(source_wallet_file.string() + ".keys", interm_wallet_file.string() + ".keys", copy_option::overwrite_if_exists);
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(interm_wallet_file.string()));
 | 
			
		||||
    ASSERT_TRUE(is_file_exist(interm_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string()))
 | 
			
		||||
        remove(target_wallet_file);
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string() + ".keys"))
 | 
			
		||||
        remove(target_wallet_file.string() + ".keys");
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    epee::wipeable_string old_password("beepbeep");
 | 
			
		||||
    epee::wipeable_string new_password("meepmeep");
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(interm_wallet_file.string(), old_password);
 | 
			
		||||
        const std::string primary_address = w.get_address_as_str();
 | 
			
		||||
        EXPECT_EQ(WALLET_00fd416a_PRIMARY_ADDRESS, primary_address);
 | 
			
		||||
        w.change_password(target_wallet_file.string(), old_password, new_password);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EXPECT_FALSE(is_file_exist(interm_wallet_file.string()));
 | 
			
		||||
    EXPECT_FALSE(is_file_exist(interm_wallet_file.string() + ".keys"));
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(target_wallet_file.string(), new_password);
 | 
			
		||||
        const std::string primary_address = w.get_address_as_str();
 | 
			
		||||
        EXPECT_EQ(WALLET_00fd416a_PRIMARY_ADDRESS, primary_address);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(wallet_storage, change_password_in_memory)
 | 
			
		||||
{
 | 
			
		||||
    const epee::wipeable_string password1("monero");
 | 
			
		||||
    const epee::wipeable_string password2("means money");
 | 
			
		||||
    const epee::wipeable_string password_wrong("is traceable");
 | 
			
		||||
 | 
			
		||||
    tools::wallet2 w;
 | 
			
		||||
    w.generate("", password1);
 | 
			
		||||
    const std::string primary_address_1 = w.get_address_as_str();
 | 
			
		||||
    w.change_password("", password1, password2);
 | 
			
		||||
    const std::string primary_address_2 = w.get_address_as_str();
 | 
			
		||||
    EXPECT_EQ(primary_address_1, primary_address_2);
 | 
			
		||||
 | 
			
		||||
    EXPECT_THROW(w.change_password("", password_wrong, password1), tools::error::invalid_password);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(wallet_storage, change_password_mem2file)
 | 
			
		||||
{
 | 
			
		||||
    const path target_wallet_file = unit_test::data_dir / "wallet_change_password_mem2file";
 | 
			
		||||
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string()))
 | 
			
		||||
        remove(target_wallet_file);
 | 
			
		||||
    if (is_file_exist(target_wallet_file.string() + ".keys"))
 | 
			
		||||
        remove(target_wallet_file.string() + ".keys");
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    ASSERT_FALSE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    const epee::wipeable_string password1("https://safecurves.cr.yp.to/rigid.html");
 | 
			
		||||
    const epee::wipeable_string password2(
 | 
			
		||||
        "https://csrc.nist.gov/csrc/media/projects/crypto-standards-development-process/documents/dualec_in_x982_and_sp800-90.pdf");
 | 
			
		||||
    
 | 
			
		||||
    std::string primary_address_1, primary_address_2;
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.generate("", password1);
 | 
			
		||||
        primary_address_1 = w.get_address_as_str();
 | 
			
		||||
        w.change_password(target_wallet_file.string(), password1, password2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string()));
 | 
			
		||||
    EXPECT_TRUE(is_file_exist(target_wallet_file.string() + ".keys"));
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        tools::wallet2 w;
 | 
			
		||||
        w.load(target_wallet_file.string(), password2);
 | 
			
		||||
        primary_address_2 = w.get_address_as_str();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EXPECT_EQ(primary_address_1, primary_address_2);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue