From 17aebd29b5ad865c65eb1663669c28430bc0287c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 14 Sep 2024 21:46:09 +0400 Subject: [PATCH] implemented custom seed option(experimental) --- src/currency_core/account.cpp | 17 ++++++--- src/currency_core/account.h | 3 ++ src/simplewallet/simplewallet.cpp | 63 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/currency_core/account.cpp b/src/currency_core/account.cpp index 6a07b7c9..f5663826 100644 --- a/src/currency_core/account.cpp +++ b/src/currency_core/account.cpp @@ -60,7 +60,7 @@ namespace currency return m_keys; } //----------------------------------------------------------------- - void crypt_with_pass(const void* scr_data, std::size_t src_length, void* dst_data, const std::string& password) + void account_base::crypt_with_pass(const void* scr_data, std::size_t src_length, void* dst_data, const std::string& password) { crypto::chacha8_key key = AUTO_VAL_INIT(key); crypto::generate_chacha8_key(password, key); @@ -71,16 +71,23 @@ namespace currency crypto::chacha8(scr_data, src_length, key, iv, (char*)dst_data); } //----------------------------------------------------------------- - std::string account_base::get_seed_phrase(const std::string& password) const + std::string account_base::get_seed_phrase(const std::string& password) const { if (m_keys_seed_binary.empty()) return ""; + return get_seed_phrase(password, m_keys_seed_binary); + } + //----------------------------------------------------------------- + std::string account_base::get_seed_phrase(const std::string& password, const std::vector& keys_seed_binary) const + { + if (keys_seed_binary.empty()) + return ""; - std::vector processed_seed_binary = m_keys_seed_binary; + std::vector processed_seed_binary = keys_seed_binary; if (!password.empty()) { //encrypt seed phrase binary data - crypt_with_pass(&m_keys_seed_binary[0], m_keys_seed_binary.size(), &processed_seed_binary[0], password); + crypt_with_pass(&keys_seed_binary[0], keys_seed_binary.size(), &processed_seed_binary[0], password); } std::string keys_seed_text = tools::mnemonic_encoding::binary2text(processed_seed_binary); @@ -92,7 +99,7 @@ namespace currency CHECK_AND_ASSERT_THROW_MES(self_check_is_password_used == !password.empty(), "Account seed phrase internal error: password flag encoded wrong"); constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum - std::string binary_for_check_sum((const char*)&m_keys_seed_binary[0], m_keys_seed_binary.size()); + std::string binary_for_check_sum((const char*)&keys_seed_binary[0], keys_seed_binary.size()); binary_for_check_sum.append(password); crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size()); *reinterpret_cast(&h) = creation_timestamp_rounded; diff --git a/src/currency_core/account.h b/src/currency_core/account.h index 37a0c953..d732181d 100644 --- a/src/currency_core/account.h +++ b/src/currency_core/account.h @@ -56,6 +56,7 @@ namespace currency std::string get_public_address_str() const; std::string get_seed_phrase(const std::string& seed_password) const; + std::string get_seed_phrase(const std::string& password, const std::vector& keys_seed_binary) const; std::string get_tracking_seed() const; bool restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password); bool restore_from_tracking_seed(const std::string& tracking_seed); @@ -82,6 +83,8 @@ namespace currency static std::vector string_to_vector_of_chars(const std::string& v) { return std::vector(v.begin(), v.end()); } static bool is_seed_password_protected(const std::string& seed_phrase, bool& is_password_protected); static bool is_seed_tracking(const std::string& seed_phrase); + static void crypt_with_pass(const void* scr_data, std::size_t src_length, void* dst_data, const std::string& password); + BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(m_keys) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 9d842fdf..f1f2ee7e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -125,6 +125,7 @@ namespace { const command_line::arg_descriptor arg_wallet_file ("wallet-file", "Use wallet ", ""); const command_line::arg_descriptor arg_generate_new_wallet ("generate-new-wallet", "Generate new wallet and save it to or
.wallet by default", ""); + const command_line::arg_descriptor arg_derive_custom_seed("derive_custom_seed", "Derive seed phrase from custom 24-words secret(advanced option, do it on your own risk)", ""); const command_line::arg_descriptor arg_generate_new_auditable_wallet ("generate-new-auditable-wallet", "Generate new auditable wallet and store it to ", ""); const command_line::arg_descriptor arg_daemon_address ("daemon-address", "Use daemon instance at :", ""); const command_line::arg_descriptor arg_daemon_host ("daemon-host", "Use daemon instance at host instead of localhost", ""); @@ -2872,7 +2873,63 @@ bool search_for_wallet_file(const std::wstring &search_here/*, const std::string return false; } +int custom_seed_builder() +{ + success_msg_writer() << + "**********************************************************************\n" << + "This is an experimental tool that helps you create a custom seed phrase \n" + "based on your own 24 words. It can be extremely unsafe, so only use it \n" + "if you're confident in what you're doing.\n" + "**********************************************************************"; + success_msg_writer() << "Please enter 24 words that you want to use as base for the seed:"; + std::string seed_24; + std::getline(std::cin, seed_24); + + + std::list words; + std::string trimed_seed_24 = epee::string_tools::trim(seed_24); + boost::split(words, trimed_seed_24, boost::is_space(), boost::token_compress_on); + seed_24 = boost::algorithm::join(words, " "); + + std::string passphrase; + success_msg_writer() << "Please enter seed passphrase(it's highly recommended to use passphrase for custom seed):"; + std::getline(std::cin, passphrase); + if (passphrase.empty()) + { + success_msg_writer() << "Using unsecured seed(no passphrase)"; + } + else + { + std::string passphrase_confirmation; + success_msg_writer() << "Please confirm passphrase:"; + std::getline(std::cin, passphrase_confirmation); + if (passphrase_confirmation != passphrase) + { + success_msg_writer() << "Passphrase mismatched, try again"; + return EXIT_FAILURE; + } + } + + account_base acc; + acc.generate(); + std::string pass_protected_or_not = ""; + std::vector binary_from_seed = tools::mnemonic_encoding::text2binary(seed_24); + std::vector processed_binary_from_seed = binary_from_seed; + if (!passphrase.empty()) + { + //encrypt seed phrase binary data + account_base::crypt_with_pass(&binary_from_seed[0], binary_from_seed.size(), &processed_binary_from_seed[0], passphrase); + pass_protected_or_not = "(secured with passphrase)"; + } + { + pass_protected_or_not = "(!without passphrase!)"; + } + const std::string new_seed = acc.get_seed_phrase(passphrase, processed_binary_from_seed); + + success_msg_writer() << "Here is your seed" << pass_protected_or_not << "\n " << new_seed; + return EXIT_SUCCESS; +} int seed_doctor() { @@ -3142,6 +3199,8 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_no_password_confirmations); command_line::add_arg(desc_params, command_line::arg_generate_rpc_autodoc); command_line::add_arg(desc_params, arg_seed_doctor); + command_line::add_arg(desc_params, arg_derive_custom_seed); + tools::wallet_rpc_server::init_options(desc_params); @@ -3225,6 +3284,10 @@ int main(int argc, char* argv[]) return seed_doctor(); } + if (command_line::has_arg(vm, arg_derive_custom_seed)) + { + return custom_seed_builder(); + } if (command_line::has_arg(vm, tools::wallet_rpc_server::arg_rpc_bind_port)) {