From 4b3e8da6fa77e2a7c02a756d9743110c5109caaf Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 19 May 2020 20:12:43 +0300 Subject: [PATCH] wallet2: made new format unloadable by old wallets + correct error on file read errors --- src/currency_core/currency_config.h | 3 ++- src/wallet/wallet2.cpp | 35 +++++++++++++++++------------ src/wallet/wallet2.h | 27 ++++++++++++++++++++-- src/wallet/wallets_manager.cpp | 4 ++++ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 760670ea..d6ab7052 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -143,7 +143,8 @@ #define POS_MINIMUM_COINSTAKE_AGE 10 // blocks count -#define WALLET_FILE_SIGNATURE 0x1111012101101011LL //Bender's nightmare +#define WALLET_FILE_SIGNATURE_OLD 0x1111012101101011LL // Bender's nightmare +#define WALLET_FILE_SIGNATURE_V2 0x111101120101011LL // another Bender's nightmare #define WALLET_FILE_MAX_BODY_SIZE 0x88888888L //2GB #define WALLET_FILE_MAX_KEYS_SIZE 10000 // #define WALLET_BRAIN_DATE_OFFSET 1543622400 diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index dfee9cdc..e923e771 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2037,20 +2037,27 @@ bool wallet2::prepare_file_names(const std::wstring& file_path) return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::load_keys(const std::string& buff, const std::string& password) +void wallet2::load_keys(const std::string& buff, const std::string& password, uint64_t file_signature) { - wallet2::keys_file_data keys_file_data; -// std::string buf; -// bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf); -// CHECK_AND_THROW_WALLET_EX(!r, error::file_read_error, keys_file_name); - bool r = ::serialization::parse_binary(buff, keys_file_data); + bool r = false; + wallet2::keys_file_data kf_data = AUTO_VAL_INIT(kf_data); + if (file_signature == WALLET_FILE_SIGNATURE_OLD) + { + wallet2::keys_file_data_old kf_data_old; + r = ::serialization::parse_binary(buff, kf_data_old); + kf_data = wallet2::keys_file_data::from_old(kf_data_old); + } + else if (file_signature == WALLET_FILE_SIGNATURE_V2) + { + r = ::serialization::parse_binary(buff, kf_data); + } THROW_IF_TRUE_WALLET_EX(!r, error::wallet_internal_error, "internal error: failed to deserialize"); crypto::chacha8_key key; crypto::generate_chacha8_key(password, key); std::string account_data; - account_data.resize(keys_file_data.account_data.size()); - crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); + account_data.resize(kf_data.account_data.size()); + crypto::chacha8(kf_data.account_data.data(), kf_data.account_data.size(), key, kf_data.iv, &account_data[0]); const currency::account_keys& keys = m_account.get_keys(); r = epee::serialization::load_t_from_binary(m_account, account_data); @@ -2131,22 +2138,22 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password) THROW_IF_TRUE_WALLET_EX(e || !exists, error::file_not_found, epee::string_encoding::convert_to_ansii(m_wallet_file)); boost::filesystem::ifstream data_file; data_file.open(m_wallet_file, std::ios_base::binary | std::ios_base::in); - THROW_IF_TRUE_WALLET_EX(data_file.fail(), error::file_not_found, epee::string_encoding::convert_to_ansii(m_wallet_file)); + THROW_IF_TRUE_WALLET_EX(data_file.fail(), error::file_read_error, epee::string_encoding::convert_to_ansii(m_wallet_file)); wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh); data_file.read((char*)&wbh, sizeof(wbh)); - THROW_IF_TRUE_WALLET_EX(data_file.fail(), error::file_not_found, epee::string_encoding::convert_to_ansii(m_wallet_file)); + THROW_IF_TRUE_WALLET_EX(data_file.fail(), error::file_read_error, epee::string_encoding::convert_to_ansii(m_wallet_file)); - THROW_IF_TRUE_WALLET_EX(wbh.m_signature != WALLET_FILE_SIGNATURE, error::file_not_found, epee::string_encoding::convert_to_ansii(m_wallet_file)); + THROW_IF_TRUE_WALLET_EX(wbh.m_signature != WALLET_FILE_SIGNATURE_OLD && wbh.m_signature != WALLET_FILE_SIGNATURE_V2, error::file_read_error, epee::string_encoding::convert_to_ansii(m_wallet_file)); THROW_IF_TRUE_WALLET_EX(wbh.m_cb_body > WALLET_FILE_MAX_BODY_SIZE || - wbh.m_cb_keys > WALLET_FILE_MAX_KEYS_SIZE, error::file_not_found, epee::string_encoding::convert_to_ansii(m_wallet_file)); + wbh.m_cb_keys > WALLET_FILE_MAX_KEYS_SIZE, error::file_read_error, epee::string_encoding::convert_to_ansii(m_wallet_file)); keys_buff.resize(wbh.m_cb_keys); data_file.read((char*)keys_buff.data(), wbh.m_cb_keys); - load_keys(keys_buff, password); + load_keys(keys_buff, password, wbh.m_signature); bool need_to_resync = !tools::portable_unserialize_obj_from_stream(*this, data_file); @@ -2188,7 +2195,7 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor //store data wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh); - wbh.m_signature = WALLET_FILE_SIGNATURE; + wbh.m_signature = WALLET_FILE_SIGNATURE_V2; wbh.m_cb_keys = keys_buff.size(); //@#@ change it to proper wbh.m_cb_body = 1000; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 7a012351..bd0913fc 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -445,7 +445,7 @@ namespace tools typedef std::map > free_amounts_cache_type; - struct keys_file_data + struct keys_file_data_old { crypto::chacha8_iv iv; std::string account_data; @@ -455,6 +455,29 @@ namespace tools FIELD(account_data) END_SERIALIZE() }; + + struct keys_file_data + { + uint8_t version; + crypto::chacha8_iv iv; + std::string account_data; + + static keys_file_data from_old(const keys_file_data_old& v) + { + keys_file_data result = AUTO_VAL_INIT(result); + result.iv = v.iv; + result.account_data = v.account_data; + return result; + } + + DEFINE_SERIALIZATION_VERSION(1) + BEGIN_SERIALIZE_OBJECT() + VERSION_ENTRY(version) + FIELD(iv) + FIELD(account_data) + END_SERIALIZE() + }; + void assign_account(const currency::account_base& acc); void generate(const std::wstring& path, const std::string& password, bool auditable_wallet); void restore(const std::wstring& path, const std::string& pass, const std::string& seed_phrase); @@ -789,7 +812,7 @@ private: void add_transfers_to_expiration_list(const std::vector& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id); void remove_transfer_from_expiration_list(uint64_t transfer_index); - void load_keys(const std::string& keys_file_name, const std::string& password); + void load_keys(const std::string& keys_file_name, const std::string& password, uint64_t file_signature); void process_new_transaction(const currency::transaction& tx, uint64_t height, const currency::block& b); void detach_blockchain(uint64_t including_height); bool extract_offers_from_transfer_entry(size_t i, std::unordered_map& offers_local); diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 483d038f..443de3e6 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -769,6 +769,10 @@ std::string wallets_manager::open_wallet(const std::wstring& path, const std::st { return API_RETURN_CODE_FILE_NOT_FOUND; } + catch (const tools::error::file_read_error&) + { + return API_RETURN_CODE_INVALID_FILE; + } catch (const tools::error::wallet_load_notice_wallet_restored& /**/) { return_code = API_RETURN_CODE_FILE_RESTORED;