diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 791309f3b..bb9049015 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -485,10 +485,28 @@ std::string simple_wallet::get_mnemonic_language() bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover, bool two_random, bool testnet, const std::string &old_language) { + bool was_deprecated_wallet = m_restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) || + crypto::ElectrumWords::get_is_old_style_seed(m_electrum_seed)); + + std::string mnemonic_language = old_language; + // Ask for seed language if it is not a wallet restore or if it was a deprecated wallet + // that was earlier used before this restore. + if (!m_restore_deterministic_wallet || was_deprecated_wallet) + { + if (was_deprecated_wallet) + { + // The user had used an older version of the wallet with old style mnemonics. + message_writer(epee::log_space::console_color_green, false) << "\nYou had been using " << + "a deprecated version of the wallet. Please use the new seed that we provide.\n"; + } + mnemonic_language = get_mnemonic_language(); + } + m_wallet_file = wallet_file; m_wallet.reset(new tools::wallet2(testnet)); m_wallet->callback(this); + m_wallet->set_seed_language(mnemonic_language); crypto::secret_key recovery_val; try @@ -509,24 +527,7 @@ bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string // convert rng value to electrum-style word list std::string electrum_words; - bool was_deprecated_wallet = m_restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) || - crypto::ElectrumWords::get_is_old_style_seed(m_electrum_seed)); - - std::string mnemonic_language = old_language; - // Ask for seed language if it is not a wallet restore or if it was a deprecated wallet - // that was earlier used before this restore. - if (!m_restore_deterministic_wallet || was_deprecated_wallet) - { - if (was_deprecated_wallet) - { - // The user had used an older version of the wallet with old style mnemonics. - message_writer(epee::log_space::console_color_green, false) << "\nYou had been using " << - "a deprecated version of the wallet. Please use the new seed that we provide.\n"; - } - mnemonic_language = get_mnemonic_language(); - } crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words, mnemonic_language); - m_wallet->set_seed_language(mnemonic_language); std::string print_electrum = ""; @@ -564,6 +565,16 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa m_wallet->load(m_wallet_file, password); message_writer(epee::log_space::console_color_white, true) << "Opened wallet: " << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + // If the wallet file is deprecated, we should ask for mnemonic language again and store + // everything in the new format. + if (!m_non_deterministic && m_wallet->is_deprecated()) + { + message_writer(epee::log_space::console_color_green, false) << "\nYou had been using " << + "a deprecated version of the wallet. Please proceed to upgrade your wallet.\n"; + std::string mnemonic_language = get_mnemonic_language(); + m_wallet->set_seed_language(mnemonic_language); + m_wallet->generate(m_wallet_file, password, m_recovery_key, false, true); + } } catch (const std::exception& e) { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5f5197891..1ac3805a7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -452,6 +452,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const std::string& p CHECK_AND_ASSERT_MES(r, false, "failed to serialize wallet keys"); wallet2::keys_file_data keys_file_data = boost::value_initialized(); + // Create a JSON object with "key_data" and "seed_language" as keys. rapidjson::Document json; json.SetObject(); rapidjson::Value value(rapidjson::kStringType); @@ -459,11 +460,14 @@ bool wallet2::store_keys(const std::string& keys_file_name, const std::string& p json.AddMember("key_data", value, json.GetAllocator()); value.SetString(seed_language.c_str(), seed_language.length()); json.AddMember("seed_language", value, json.GetAllocator()); + + // Serialize the JSON object rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); json.Accept(writer); - account_data = buffer.GetString(); + + // Encrypt the entire JSON object. crypto::chacha8_key key; crypto::generate_chacha8_key(password, key); std::string cipher; @@ -497,6 +501,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name); + // Decrypt the contents r = ::serialization::parse_binary(buf, keys_file_data); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"'); crypto::chacha8_key key; @@ -505,6 +510,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa 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]); + // The contents should be JSON if the wallet follows the new format. rapidjson::Document json; if (json.Parse(account_data.c_str(), keys_file_data.account_data.size()).HasParseError()) { @@ -514,9 +520,8 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa { account_data = std::string(json["key_data"].GetString(), json["key_data"].GetString() + json["key_data"].GetStringLength()); - std::cout << "A/C " << json["key_data"].GetStringLength() << std::endl; - seed_language = std::string(json["seed_language"].GetString(), json["seed_language"].GetString() + - json["seed_language"].GetStringLength()); + set_seed_language(std::string(json["seed_language"].GetString(), json["seed_language"].GetString() + + json["seed_language"].GetStringLength())); } const cryptonote::account_keys& keys = m_account.get_keys(); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 35e02ce28..10b4d6f3f 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -82,7 +82,7 @@ namespace tools { wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false) {}; public: - wallet2(bool testnet = false) : m_run(true), m_callback(0), m_testnet(testnet) {}; + wallet2(bool testnet = false) : m_run(true), m_callback(0), m_testnet(testnet), is_old_file_format(false) {}; struct transfer_details { uint64_t m_block_height;