wallet2 / simplewallet: Must opt-in to create '.address.txt' files for new wallets

Previously, a file containing the unencrypted Monero address was
created by default in the wallet's directory. This file might pose
as a privacy risk. The creation of this file is now opt-in and can
be enabled by providing

    --create-address-file
This commit is contained in:
Leon Klingele 2018-02-25 17:59:52 +01:00
parent 0d150aca5c
commit 649a1b7ae6
No known key found for this signature in database
GPG key ID: 83AEC0FEBAA5D483
4 changed files with 90 additions and 51 deletions

View file

@ -73,11 +73,12 @@ namespace
const command_line::arg_descriptor<uint32_t> arg_threshold = {"threshold", genms::tr("How many signers are required to sign a valid transaction"), 0}; const command_line::arg_descriptor<uint32_t> arg_threshold = {"threshold", genms::tr("How many signers are required to sign a valid transaction"), 0};
const command_line::arg_descriptor<bool, false> arg_testnet = {"testnet", genms::tr("Create testnet multisig wallets"), false}; const command_line::arg_descriptor<bool, false> arg_testnet = {"testnet", genms::tr("Create testnet multisig wallets"), false};
const command_line::arg_descriptor<bool, false> arg_stagenet = {"stagenet", genms::tr("Create stagenet multisig wallets"), false}; const command_line::arg_descriptor<bool, false> arg_stagenet = {"stagenet", genms::tr("Create stagenet multisig wallets"), false};
const command_line::arg_descriptor<bool, false> arg_create_address_file = {"create-address-file", genms::tr("Create an address file for new wallets"), false};
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""}; const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
} }
static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype) static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype, bool create_address_file)
{ {
tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str(); tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str();
@ -92,7 +93,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str
std::string name = basename + "-" + std::to_string(n + 1); std::string name = basename + "-" + std::to_string(n + 1);
wallets[n].reset(new tools::wallet2(nettype)); wallets[n].reset(new tools::wallet2(nettype));
wallets[n]->init(""); wallets[n]->init("");
wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false); wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false, create_address_file);
} }
// gather the keys // gather the keys
@ -171,6 +172,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_participants); command_line::add_arg(desc_params, arg_participants);
command_line::add_arg(desc_params, arg_testnet); command_line::add_arg(desc_params, arg_testnet);
command_line::add_arg(desc_params, arg_stagenet); command_line::add_arg(desc_params, arg_stagenet);
command_line::add_arg(desc_params, arg_create_address_file);
const auto vm = wallet_args::main( const auto vm = wallet_args::main(
argc, argv, argc, argv,
@ -241,7 +243,8 @@ int main(int argc, char* argv[])
tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported"); tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported");
return 1; return 1;
} }
if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET)) bool create_address_file = command_line::get_arg(*vm, arg_create_address_file);
if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET, create_address_file))
return 1; return 1;
return 0; return 0;

View file

@ -134,6 +134,7 @@ namespace
const command_line::arg_descriptor<bool> arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false}; const command_line::arg_descriptor<bool> arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false};
const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0}; const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0};
const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the monero network"), false}; const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the monero network"), false};
const command_line::arg_descriptor<bool> arg_create_address_file = {"create-address-file", sw::tr("Create an address file for new wallets"), false};
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""}; const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
@ -2848,10 +2849,12 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
m_wallet->set_seed_language(mnemonic_language); m_wallet->set_seed_language(mnemonic_language);
bool create_address_file = command_line::get_arg(vm, arg_create_address_file);
crypto::secret_key recovery_val; crypto::secret_key recovery_val;
try try
{ {
recovery_val = m_wallet->generate(m_wallet_file, std::move(rc.second).password(), recovery_key, recover, two_random); recovery_val = m_wallet->generate(m_wallet_file, std::move(rc.second).password(), recovery_key, recover, two_random, create_address_file);
message_writer(console_color_white, true) << tr("Generated new wallet: ") message_writer(console_color_white, true) << tr("Generated new wallet: ")
<< m_wallet->get_account().get_public_address_str(m_wallet->nettype()); << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL; std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL;
@ -2900,15 +2903,17 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
if (m_restore_height) if (m_restore_height)
m_wallet->set_refresh_from_block_height(m_restore_height); m_wallet->set_refresh_from_block_height(m_restore_height);
bool create_address_file = command_line::get_arg(vm, arg_create_address_file);
try try
{ {
if (spendkey) if (spendkey)
{ {
m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, *spendkey, viewkey); m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, *spendkey, viewkey, create_address_file);
} }
else else
{ {
m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey); m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey, create_address_file);
} }
message_writer(console_color_white, true) << tr("Generated new wallet: ") message_writer(console_color_white, true) << tr("Generated new wallet: ")
<< m_wallet->get_account().get_public_address_str(m_wallet->nettype()); << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
@ -2971,9 +2976,11 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
m_wallet->set_seed_language(mnemonic_language); m_wallet->set_seed_language(mnemonic_language);
bool create_address_file = command_line::get_arg(vm, arg_create_address_file);
try try
{ {
m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys); m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys, create_address_file);
bool ready; bool ready;
uint32_t threshold, total; uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total) || !ready) if (!m_wallet->multisig(&ready, &threshold, &total) || !ready)
@ -6979,6 +6986,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version); command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version);
command_line::add_arg(desc_params, arg_restore_height); command_line::add_arg(desc_params, arg_restore_height);
command_line::add_arg(desc_params, arg_do_not_relay); command_line::add_arg(desc_params, arg_do_not_relay);
command_line::add_arg(desc_params, arg_create_address_file);
po::positional_options_description positional_options; po::positional_options_description positional_options;
positional_options.add(arg_command.name, -1); positional_options.add(arg_command.name, -1);

View file

@ -318,6 +318,9 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, address, std::string, String, false, std::string()); GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, address, std::string, String, false, std::string());
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, create_address_file, int, Int, false, false);
bool create_address_file = field_create_address_file;
// compatibility checks // compatibility checks
if (!field_seed_found && !field_viewkey_found && !field_spendkey_found) if (!field_seed_found && !field_viewkey_found && !field_spendkey_found)
{ {
@ -372,11 +375,11 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
{ {
if (!field_seed.empty()) if (!field_seed.empty())
{ {
wallet->generate(field_filename, field_password, recovery_key, recover, false); wallet->generate(field_filename, field_password, recovery_key, recover, false, create_address_file);
} }
else if (field_viewkey.empty() && !field_spendkey.empty()) else if (field_viewkey.empty() && !field_spendkey.empty())
{ {
wallet->generate(field_filename, field_password, spendkey, recover, false); wallet->generate(field_filename, field_password, spendkey, recover, false, create_address_file);
} }
else else
{ {
@ -402,14 +405,14 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
{ {
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Address must be specified in order to create watch-only wallet")); THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Address must be specified in order to create watch-only wallet"));
} }
wallet->generate(field_filename, field_password, address, viewkey); wallet->generate(field_filename, field_password, address, viewkey, create_address_file);
} }
else else
{ {
if (!crypto::secret_key_to_public_key(spendkey, address.m_spend_public_key)) { if (!crypto::secret_key_to_public_key(spendkey, address.m_spend_public_key)) {
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key")); THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
} }
wallet->generate(field_filename, field_password, address, spendkey, viewkey); wallet->generate(field_filename, field_password, address, spendkey, viewkey, create_address_file);
} }
} }
} }
@ -2740,7 +2743,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
* \param multisig_data The multisig restore info and keys * \param multisig_data The multisig restore info and keys
*/ */
void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
const std::string& multisig_data) const std::string& multisig_data, bool create_address_file)
{ {
clear(); clear();
prepare_file_names(wallet_); prepare_file_names(wallet_);
@ -2812,9 +2815,12 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, false); bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (m_nettype != MAINNET || create_address_file)
{
r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved"); if(!r) MERROR("String with address text not saved");
} }
}
cryptonote::block b; cryptonote::block b;
generate_genesis(b); generate_genesis(b);
@ -2835,7 +2841,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
* \return The secret key of the generated wallet * \return The secret key of the generated wallet
*/ */
crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
const crypto::secret_key& recovery_param, bool recover, bool two_random) const crypto::secret_key& recovery_param, bool recover, bool two_random, bool create_address_file)
{ {
clear(); clear();
prepare_file_names(wallet_); prepare_file_names(wallet_);
@ -2866,9 +2872,12 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
bool r = store_keys(m_keys_file, password, false); bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (m_nettype != MAINNET || create_address_file)
{
r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved"); if(!r) MERROR("String with address text not saved");
} }
}
cryptonote::block b; cryptonote::block b;
generate_genesis(b); generate_genesis(b);
@ -2931,7 +2940,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
*/ */
void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
const cryptonote::account_public_address &account_public_address, const cryptonote::account_public_address &account_public_address,
const crypto::secret_key& viewkey) const crypto::secret_key& viewkey, bool create_address_file)
{ {
clear(); clear();
prepare_file_names(wallet_); prepare_file_names(wallet_);
@ -2956,9 +2965,12 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, true); bool r = store_keys(m_keys_file, password, true);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (m_nettype != MAINNET || create_address_file)
{
r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved"); if(!r) MERROR("String with address text not saved");
} }
}
cryptonote::block b; cryptonote::block b;
generate_genesis(b); generate_genesis(b);
@ -2978,7 +2990,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
*/ */
void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password, void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
const cryptonote::account_public_address &account_public_address, const cryptonote::account_public_address &account_public_address,
const crypto::secret_key& spendkey, const crypto::secret_key& viewkey) const crypto::secret_key& spendkey, const crypto::secret_key& viewkey, bool create_address_file)
{ {
clear(); clear();
prepare_file_names(wallet_); prepare_file_names(wallet_);
@ -3003,9 +3015,12 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, false); bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (m_nettype != MAINNET || create_address_file)
{
r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved"); if(!r) MERROR("String with address text not saved");
} }
}
cryptonote::block b; cryptonote::block b;
generate_genesis(b); generate_genesis(b);
@ -3136,9 +3151,12 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
bool r = store_keys(m_keys_file, password, false); bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (boost::filesystem::exists(m_wallet_file + ".address.txt"))
{
r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved"); if(!r) MERROR("String with address text not saved");
} }
}
cryptonote::block b; cryptonote::block b;
generate_genesis(b); generate_genesis(b);
@ -3236,9 +3254,12 @@ bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unor
bool r = store_keys(m_keys_file, password, false); bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (boost::filesystem::exists(m_wallet_file + ".address.txt"))
{
r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved"); if(!r) MERROR("String with address text not saved");
} }
}
m_subaddresses.clear(); m_subaddresses.clear();
m_subaddress_labels.clear(); m_subaddress_labels.clear();
@ -3760,10 +3781,13 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
prepare_file_names(path); prepare_file_names(path);
bool r = store_keys(m_keys_file, password, false); bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
if (boost::filesystem::exists(old_address_file))
{
// save address to the new file // save address to the new file
const std::string address_file = m_wallet_file + ".address.txt"; const std::string address_file = m_wallet_file + ".address.txt";
r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype)); r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype));
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file);
}
// remove old wallet file // remove old wallet file
r = boost::filesystem::remove(old_file); r = boost::filesystem::remove(old_file);
if (!r) { if (!r) {

View file

@ -452,9 +452,10 @@ namespace tools
* \param wallet_ Name of wallet file * \param wallet_ Name of wallet file
* \param password Password of wallet file * \param password Password of wallet file
* \param multisig_data The multisig restore info and keys * \param multisig_data The multisig restore info and keys
* \param create_address_file Whether to create an address file
*/ */
void generate(const std::string& wallet_, const epee::wipeable_string& password, void generate(const std::string& wallet_, const epee::wipeable_string& password,
const std::string& multisig_data); const std::string& multisig_data, bool create_address_file = false);
/*! /*!
* \brief Generates a wallet or restores one. * \brief Generates a wallet or restores one.
@ -463,30 +464,33 @@ namespace tools
* \param recovery_param If it is a restore, the recovery key * \param recovery_param If it is a restore, the recovery key
* \param recover Whether it is a restore * \param recover Whether it is a restore
* \param two_random Whether it is a non-deterministic wallet * \param two_random Whether it is a non-deterministic wallet
* \param create_address_file Whether to create an address file
* \return The secret key of the generated wallet * \return The secret key of the generated wallet
*/ */
crypto::secret_key generate(const std::string& wallet, const epee::wipeable_string& password, crypto::secret_key generate(const std::string& wallet, const epee::wipeable_string& password,
const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false,
bool two_random = false); bool two_random = false, bool create_address_file = false);
/*! /*!
* \brief Creates a wallet from a public address and a spend/view secret key pair. * \brief Creates a wallet from a public address and a spend/view secret key pair.
* \param wallet_ Name of wallet file * \param wallet_ Name of wallet file
* \param password Password of wallet file * \param password Password of wallet file
* \param viewkey view secret key * \param viewkey view secret key
* \param spendkey spend secret key * \param spendkey spend secret key
* \param create_address_file Whether to create an address file
*/ */
void generate(const std::string& wallet, const epee::wipeable_string& password, void generate(const std::string& wallet, const epee::wipeable_string& password,
const cryptonote::account_public_address &account_public_address, const cryptonote::account_public_address &account_public_address,
const crypto::secret_key& spendkey, const crypto::secret_key& viewkey); const crypto::secret_key& spendkey, const crypto::secret_key& viewkey, bool create_address_file = false);
/*! /*!
* \brief Creates a watch only wallet from a public address and a view secret key. * \brief Creates a watch only wallet from a public address and a view secret key.
* \param wallet_ Name of wallet file * \param wallet_ Name of wallet file
* \param password Password of wallet file * \param password Password of wallet file
* \param viewkey view secret key * \param viewkey view secret key
* \param create_address_file Whether to create an address file
*/ */
void generate(const std::string& wallet, const epee::wipeable_string& password, void generate(const std::string& wallet, const epee::wipeable_string& password,
const cryptonote::account_public_address &account_public_address, const cryptonote::account_public_address &account_public_address,
const crypto::secret_key& viewkey = crypto::secret_key()); const crypto::secret_key& viewkey = crypto::secret_key(), bool create_address_file = false);
/*! /*!
* \brief Restore a wallet hold by an HW. * \brief Restore a wallet hold by an HW.
* \param wallet_ Name of wallet file * \param wallet_ Name of wallet file