From 1dc3b1a516332f12a4bd8fd8dd80695a003d1d98 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 6 Jun 2019 09:50:56 +0000 Subject: [PATCH] wallet: add --extra-entropy command line flag It lets the user add custom entropy to the PRNG. It does this by hashing the new data and xoring the resulting hash with the PRNG state. --- src/crypto/crypto.cpp | 15 +++++++++++++-- src/crypto/crypto.h | 1 + src/crypto/random.c | 15 +++++++++++++++ src/crypto/random.h | 1 + src/wallet/wallet2.cpp | 11 +++++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 3f06c4f3f..6d3c4ed35 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -88,13 +88,24 @@ namespace crypto { return &reinterpret_cast(scalar); } - void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes) + boost::mutex &get_random_lock() { static boost::mutex random_lock; - boost::lock_guard lock(random_lock); + return random_lock; + } + + void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes) + { + boost::lock_guard lock(get_random_lock()); generate_random_bytes_not_thread_safe(N, bytes); } + void add_extra_entropy_thread_safe(const void *ptr, size_t bytes) + { + boost::lock_guard lock(get_random_lock()); + add_extra_entropy_not_thread_safe(ptr, bytes); + } + static inline bool less32(const unsigned char *k0, const unsigned char *k1) { for (int n = 31; n >= 0; --n) diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index bac456f60..8ce321f71 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -147,6 +147,7 @@ namespace crypto { }; void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes); + void add_extra_entropy_thread_safe(const void *ptr, size_t bytes); /* Generate N random bytes */ diff --git a/src/crypto/random.c b/src/crypto/random.c index 74b202661..766b5f558 100644 --- a/src/crypto/random.c +++ b/src/crypto/random.c @@ -146,3 +146,18 @@ void generate_random_bytes_not_thread_safe(size_t n, void *result) { } } } + +void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes) +{ + size_t i; + + while (bytes > 0) + { + hash_permutation(&state); + const size_t round_bytes = bytes > HASH_DATA_AREA ? HASH_DATA_AREA : bytes; + for (i = 0; i < round_bytes; ++i) + state.b[i] ^= ((const uint8_t*)ptr)[i]; + bytes -= round_bytes; + ptr = cpadd(ptr, round_bytes); + } +} diff --git a/src/crypto/random.h b/src/crypto/random.h index ccb9f4853..21a66d776 100644 --- a/src/crypto/random.h +++ b/src/crypto/random.h @@ -33,3 +33,4 @@ #include void generate_random_bytes_not_thread_safe(size_t n, void *result); +void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f25e9ad97..d382e5f92 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -273,6 +273,7 @@ struct options { const command_line::arg_descriptor tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" }; const command_line::arg_descriptor no_dns = {"no-dns", tools::wallet2::tr("Do not use DNS"), false}; const command_line::arg_descriptor offline = {"offline", tools::wallet2::tr("Do not connect to a daemon, nor use DNS"), false}; + const command_line::arg_descriptor extra_entropy = {"extra-entropy", tools::wallet2::tr("File containing extra entropy to initialize the PRNG (any data, aim for 256 bits of entropy to be useful, wihch typically means more than 256 bits of data)")}; }; void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file, std::string &mms_file) @@ -474,6 +475,15 @@ std::unique_ptr make_basic(const boost::program_options::variabl if (command_line::get_arg(vm, opts.offline)) wallet->set_offline(); + const std::string extra_entropy = command_line::get_arg(vm, opts.extra_entropy); + if (!extra_entropy.empty()) + { + std::string data; + THROW_WALLET_EXCEPTION_IF(!epee::file_io_utils::load_file_to_string(extra_entropy, data), + tools::error::wallet_internal_error, "Failed to load extra entropy from " + extra_entropy); + add_extra_entropy_thread_safe(data.data(), data.size()); + } + try { if (!command_line::is_arg_defaulted(vm, opts.tx_notify)) @@ -1198,6 +1208,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.tx_notify); command_line::add_arg(desc_params, opts.no_dns); command_line::add_arg(desc_params, opts.offline); + command_line::add_arg(desc_params, opts.extra_entropy); } std::pair, tools::password_container> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function(const char *, bool)> &password_prompter)