wallet: allow adjusting number of rounds for the key derivation function

This commit is contained in:
stoffu 2018-07-06 15:42:08 +09:00
parent 0dddfeacc9
commit bcab579864
No known key found for this signature in database
GPG key ID: 41DAB8343A9EC012
14 changed files with 76 additions and 52 deletions

View file

@ -69,22 +69,26 @@ namespace crypto {
chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher);
}
inline void generate_chacha_key(const void *data, size_t size, chacha_key& key) {
inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, uint64_t kdf_rounds) {
static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key");
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 0/*prehashed*/);
for (uint64_t n = 1; n < kdf_rounds; ++n)
crypto::cn_slow_hash(pwd_hash.data(), pwd_hash.size(), pwd_hash.data(), 0/*variant*/, 0/*prehashed*/);
memcpy(&unwrap(key), pwd_hash.data(), sizeof(key));
}
inline void generate_chacha_key_prehashed(const void *data, size_t size, chacha_key& key) {
inline void generate_chacha_key_prehashed(const void *data, size_t size, chacha_key& key, uint64_t kdf_rounds) {
static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key");
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 1/*prehashed*/);
for (uint64_t n = 1; n < kdf_rounds; ++n)
crypto::cn_slow_hash(pwd_hash.data(), pwd_hash.size(), pwd_hash.data(), 0/*variant*/, 0/*prehashed*/);
memcpy(&unwrap(key), pwd_hash.data(), sizeof(key));
}
inline void generate_chacha_key(std::string password, chacha_key& key) {
return generate_chacha_key(password.data(), password.size(), key);
inline void generate_chacha_key(std::string password, chacha_key& key, uint64_t kdf_rounds) {
return generate_chacha_key(password.data(), password.size(), key, kdf_rounds);
}
}

View file

@ -125,7 +125,7 @@ namespace hw {
/* ======================================================================= */
virtual bool get_public_address(cryptonote::account_public_address &pubkey) = 0;
virtual bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) = 0;
virtual bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) = 0;
virtual bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) = 0;
/* ======================================================================= */
/* SUB ADDRESS */

View file

@ -100,14 +100,14 @@ namespace hw {
/* WALLET & ADDRESS */
/* ======================================================================= */
bool device_default::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) {
bool device_default::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) {
const crypto::secret_key &view_key = keys.m_view_secret_key;
const crypto::secret_key &spend_key = keys.m_spend_secret_key;
tools::scrubbed_arr<char, sizeof(view_key) + sizeof(spend_key) + 1> data;
memcpy(data.data(), &view_key, sizeof(view_key));
memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key));
data[sizeof(data) - 1] = CHACHA8_KEY_TAIL;
crypto::generate_chacha_key(data.data(), sizeof(data), key);
crypto::generate_chacha_key(data.data(), sizeof(data), key, kdf_rounds);
return true;
}
bool device_default::get_public_address(cryptonote::account_public_address &pubkey) {

View file

@ -73,7 +73,7 @@ namespace hw {
/* ======================================================================= */
bool get_public_address(cryptonote::account_public_address &pubkey) override;
bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) override;
bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) override;
bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) override;
/* ======================================================================= */
/* SUB ADDRESS */

View file

@ -531,20 +531,20 @@ namespace hw {
return true;
}
bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) {
bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) {
AUTO_LOCK_CMD();
#ifdef DEBUG_HWDEVICE
crypto::chacha_key key_x;
cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
this->controle_device->generate_chacha_key(keys_x, key_x);
this->controle_device->generate_chacha_key(keys_x, key_x, kdf_rounds);
#endif
send_simple(INS_GET_CHACHA8_PREKEY);
char prekey[200];
memmove(prekey, &this->buffer_recv[0], 200);
crypto::generate_chacha_key_prehashed(&prekey[0], sizeof(prekey), key);
crypto::generate_chacha_key_prehashed(&prekey[0], sizeof(prekey), key, kdf_rounds);
#ifdef DEBUG_HWDEVICE
hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data());

View file

@ -156,7 +156,7 @@ namespace hw {
/* ======================================================================= */
bool get_public_address(cryptonote::account_public_address &pubkey) override;
bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) override;
bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) override;
bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) override;
/* ======================================================================= */

View file

@ -366,7 +366,7 @@ void Wallet::error(const std::string &category, const std::string &str) {
}
///////////////////////// WalletImpl implementation ////////////////////////
WalletImpl::WalletImpl(NetworkType nettype)
WalletImpl::WalletImpl(NetworkType nettype, bool restricted, uint64_t kdf_rounds)
:m_wallet(nullptr)
, m_status(Wallet::Status_Ok)
, m_trustedDaemon(false)
@ -377,7 +377,7 @@ WalletImpl::WalletImpl(NetworkType nettype)
, m_rebuildWalletCache(false)
, m_is_connected(false)
{
m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype));
m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype), restricted, kdf_rounds);
m_history = new TransactionHistoryImpl(this);
m_wallet2Callback = new Wallet2CallbackImpl(this);
m_wallet->callback(m_wallet2Callback);

View file

@ -52,7 +52,7 @@ struct Wallet2CallbackImpl;
class WalletImpl : public Wallet
{
public:
WalletImpl(NetworkType nettype = MAINNET);
WalletImpl(NetworkType nettype = MAINNET, bool restricted = false, uint64_t kdf_rounds = 1);
~WalletImpl();
bool create(const std::string &path, const std::string &password,
const std::string &language);

View file

@ -920,9 +920,10 @@ struct WalletManager
* \param password Password of wallet file
* \param language Language to be used to generate electrum seed mnemonic
* \param nettype Network type
* \param kdf_rounds Number of rounds for key derivation function
* \return Wallet instance (Wallet::status() needs to be called to check if created successfully)
*/
virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype) = 0;
virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype, uint64_t kdf_rounds = 1) = 0;
Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) // deprecated
{
return createWallet(path, password, language, testnet ? TESTNET : MAINNET);
@ -933,9 +934,10 @@ struct WalletManager
* \param path Name of wallet file
* \param password Password of wallet file
* \param nettype Network type
* \param kdf_rounds Number of rounds for key derivation function
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
*/
virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype) = 0;
virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) = 0;
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
{
return openWallet(path, password, testnet ? TESTNET : MAINNET);
@ -948,10 +950,11 @@ struct WalletManager
* \param mnemonic mnemonic (25 words electrum seed)
* \param nettype Network type
* \param restoreHeight restore from start height
* \param kdf_rounds Number of rounds for key derivation function
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0;
NetworkType nettype = MAINNET, uint64_t restoreHeight = 0, uint64_t kdf_rounds = 1) = 0;
Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
bool testnet = false, uint64_t restoreHeight = 0) // deprecated
{
@ -983,6 +986,7 @@ struct WalletManager
* \param addressString public address
* \param viewKeyString view key
* \param spendKeyString spend key (optional)
* \param kdf_rounds Number of rounds for key derivation function
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletFromKeys(const std::string &path,
@ -992,7 +996,8 @@ struct WalletManager
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
const std::string &spendKeyString = "",
uint64_t kdf_rounds = 1) = 0;
Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
@ -1043,6 +1048,7 @@ struct WalletManager
* \param deviceName Device name
* \param restoreHeight restore from start height (0 sets to current height)
* \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value)
* \param kdf_rounds Number of rounds for key derivation function
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletFromDevice(const std::string &path,
@ -1050,7 +1056,8 @@ struct WalletManager
NetworkType nettype,
const std::string &deviceName,
uint64_t restoreHeight = 0,
const std::string &subaddressLookahead = "") = 0;
const std::string &subaddressLookahead = "",
uint64_t kdf_rounds = 1) = 0;
/*!
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
@ -1075,13 +1082,14 @@ struct WalletManager
* @param keys_file_name - location of keys file
* @param password - password to verify
* @param no_spend_key - verify only view keys?
* @param kdf_rounds - number of rounds for key derivation function
* @return - true if password is correct
*
* @note
* This function will fail when the wallet keys file is opened because the wallet program locks the keys file.
* In this case, Wallet::unlockKeysFile() and Wallet::lockKeysFile() need to be called before and after the call to this function, respectively.
*/
virtual bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const = 0;
virtual bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const = 0;
/*!
* \brief findWallets - searches for the wallet files by given path name recursively

View file

@ -50,16 +50,16 @@ namespace epee {
namespace Monero {
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
const std::string &language, NetworkType nettype)
const std::string &language, NetworkType nettype, uint64_t kdf_rounds)
{
WalletImpl * wallet = new WalletImpl(nettype);
WalletImpl * wallet = new WalletImpl(nettype, false, kdf_rounds);
wallet->create(path, password, language);
return wallet;
}
Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype)
Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds)
{
WalletImpl * wallet = new WalletImpl(nettype);
WalletImpl * wallet = new WalletImpl(nettype, false, kdf_rounds);
wallet->open(path, password);
//Refresh addressBook
wallet->addressBook()->refresh();
@ -87,9 +87,10 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
NetworkType nettype,
uint64_t restoreHeight)
uint64_t restoreHeight,
uint64_t kdf_rounds)
{
WalletImpl * wallet = new WalletImpl(nettype);
WalletImpl * wallet = new WalletImpl(nettype, false, kdf_rounds);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
@ -104,9 +105,10 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString)
const std::string &spendKeyString,
uint64_t kdf_rounds)
{
WalletImpl * wallet = new WalletImpl(nettype);
WalletImpl * wallet = new WalletImpl(nettype, false, kdf_rounds);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
@ -119,9 +121,10 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
NetworkType nettype,
const std::string &deviceName,
uint64_t restoreHeight,
const std::string &subaddressLookahead)
const std::string &subaddressLookahead,
uint64_t kdf_rounds)
{
WalletImpl * wallet = new WalletImpl(nettype);
WalletImpl * wallet = new WalletImpl(nettype, false, kdf_rounds);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
@ -159,9 +162,9 @@ bool WalletManagerImpl::walletExists(const std::string &path)
return false;
}
bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const
bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds) const
{
return tools::wallet2::verify_password(keys_file_name, password, no_spend_key, hw::get_device("default"));
return tools::wallet2::verify_password(keys_file_name, password, no_spend_key, hw::get_device("default"), kdf_rounds);
}
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)

View file

@ -39,13 +39,14 @@ class WalletManagerImpl : public WalletManager
{
public:
Wallet * createWallet(const std::string &path, const std::string &password,
const std::string &language, NetworkType nettype) override;
Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype) override;
const std::string &language, NetworkType nettype, uint64_t kdf_rounds = 1) override;
Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) override;
virtual Wallet * recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
NetworkType nettype,
uint64_t restoreHeight) override;
uint64_t restoreHeight,
uint64_t kdf_rounds = 1) override;
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
@ -53,7 +54,8 @@ public:
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") override;
const std::string &spendKeyString = "",
uint64_t kdf_rounds = 1) override;
// next two methods are deprecated - use the above version which allow setting of a password
virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight) override;
// deprecated: use createWalletFromKeys(..., password, ...) instead
@ -69,10 +71,11 @@ public:
NetworkType nettype,
const std::string &deviceName,
uint64_t restoreHeight = 0,
const std::string &subaddressLookahead = "") override;
const std::string &subaddressLookahead = "",
uint64_t kdf_rounds = 1) override;
virtual bool closeWallet(Wallet *wallet, bool store = true) override;
bool walletExists(const std::string &path) override;
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const override;
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override;
std::vector<std::string> findWallets(const std::string &path) override;
std::string errorString() const override;
void setDaemonAddress(const std::string &address) override;

View file

@ -160,6 +160,7 @@ struct options {
return val;
}
};
const command_line::arg_descriptor<uint64_t> kdf_rounds = {"kdf-rounds", tools::wallet2::tr("Number of rounds for the key derivation function"), 1};
};
void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file)
@ -203,6 +204,8 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
const bool stagenet = command_line::get_arg(vm, opts.stagenet);
const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
const bool restricted = command_line::get_arg(vm, opts.restricted);
const uint64_t kdf_rounds = command_line::get_arg(vm, opts.kdf_rounds);
THROW_WALLET_EXCEPTION_IF(kdf_rounds == 0, tools::error::wallet_internal_error, "KDF rounds must not be 0");
auto daemon_address = command_line::get_arg(vm, opts.daemon_address);
auto daemon_host = command_line::get_arg(vm, opts.daemon_host);
@ -236,7 +239,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
if (daemon_address.empty())
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, restricted));
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, restricted, kdf_rounds));
wallet->init(std::move(daemon_address), std::move(login));
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
wallet->set_ring_database(ringdb_path.string());
@ -647,7 +650,7 @@ const size_t MAX_SPLIT_ATTEMPTS = 30;
constexpr const std::chrono::seconds wallet2::rpc_timeout;
const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); }
wallet2::wallet2(network_type nettype, bool restricted):
wallet2::wallet2(network_type nettype, bool restricted, uint64_t kdf_rounds):
m_multisig_rescan_info(NULL),
m_multisig_rescan_k(NULL),
m_run(true),
@ -679,6 +682,7 @@ wallet2::wallet2(network_type nettype, bool restricted):
m_ignore_fractional_outputs(true),
m_is_initialized(false),
m_restricted(restricted),
m_kdf_rounds(kdf_rounds),
is_old_file_format(false),
m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex),
m_subaddress_lookahead_major(SUBADDRESS_LOOKAHEAD_MAJOR),
@ -723,6 +727,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.stagenet);
command_line::add_arg(desc_params, opts.restricted);
command_line::add_arg(desc_params, opts.shared_ringdb_dir);
command_line::add_arg(desc_params, opts.kdf_rounds);
}
std::unique_ptr<wallet2> wallet2::make_from_json(const boost::program_options::variables_map& vm, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
@ -2844,7 +2849,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
// Encrypt the entire JSON object.
crypto::chacha_key key;
crypto::generate_chacha_key(password.data(), password.size(), key);
crypto::generate_chacha_key(password.data(), password.size(), key, m_kdf_rounds);
std::string cipher;
cipher.resize(account_data.size());
keys_file_data.iv = crypto::rand<crypto::chacha_iv>();
@ -2878,7 +2883,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
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::chacha_key key;
crypto::generate_chacha_key(password.data(), password.size(), key);
crypto::generate_chacha_key(password.data(), password.size(), key, m_kdf_rounds);
std::string account_data;
account_data.resize(keys_file_data.account_data.size());
crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
@ -3084,7 +3089,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password)
{
// this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded).
unlock_keys_file();
bool r = verify_password(m_keys_file, password, m_watch_only || m_multisig, m_account.get_device());
bool r = verify_password(m_keys_file, password, m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds);
lock_keys_file();
return r;
}
@ -3102,7 +3107,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password)
* can be used prior to rewriting wallet keys file, to ensure user has entered the correct password
*
*/
bool wallet2::verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev)
bool wallet2::verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds)
{
rapidjson::Document json;
wallet2::keys_file_data keys_file_data;
@ -3114,7 +3119,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
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::chacha_key key;
crypto::generate_chacha_key(password.data(), password.size(), key);
crypto::generate_chacha_key(password.data(), password.size(), key, kdf_rounds);
std::string account_data;
account_data.resize(keys_file_data.account_data.size());
crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
@ -3982,7 +3987,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
bool wallet2::generate_chacha_key_from_secret_keys(crypto::chacha_key &key) const
{
hw::device &hwdev = m_account.get_device();
return hwdev.generate_chacha_key(m_account.get_keys(), key);
return hwdev.generate_chacha_key(m_account.get_keys(), key, m_kdf_rounds);
}
//----------------------------------------------------------------------------------------------------
void wallet2::load(const std::string& wallet_, const epee::wipeable_string& password)
@ -10534,7 +10539,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
std::string wallet2::encrypt(const std::string &plaintext, const crypto::secret_key &skey, bool authenticated) const
{
crypto::chacha_key key;
crypto::generate_chacha_key(&skey, sizeof(skey), key);
crypto::generate_chacha_key(&skey, sizeof(skey), key, m_kdf_rounds);
std::string ciphertext;
crypto::chacha_iv iv = crypto::rand<crypto::chacha_iv>();
ciphertext.resize(plaintext.size() + sizeof(iv) + (authenticated ? sizeof(crypto::signature) : 0));
@ -10564,7 +10569,7 @@ std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret
error::wallet_internal_error, "Unexpected ciphertext size");
crypto::chacha_key key;
crypto::generate_chacha_key(&skey, sizeof(skey), key);
crypto::generate_chacha_key(&skey, sizeof(skey), key, m_kdf_rounds);
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
std::string plaintext;
plaintext.resize(ciphertext.size() - prefix_size);

View file

@ -165,9 +165,9 @@ namespace tools
//! Just parses variables.
static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev);
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds);
wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, bool restricted = false);
wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, bool restricted = false, uint64_t kdf_rounds = 1);
~wallet2();
struct multisig_info
@ -1258,6 +1258,7 @@ namespace tools
bool m_key_on_device;
cryptonote::network_type m_nettype;
bool m_restricted;
uint64_t m_kdf_rounds;
std::string seed_language; /*!< Language of the mnemonics (seed). */
bool is_old_file_format; /*!< Whether the wallet file is of an old file format */
bool m_watch_only; /*!< no spend key */

View file

@ -810,7 +810,7 @@ TEST(Serialization, portability_outputs)
if(ciphertext.size() < prefix_size)
return {};
crypto::chacha_key key;
crypto::generate_chacha_key(&skey, sizeof(skey), key);
crypto::generate_chacha_key(&skey, sizeof(skey), key, 1);
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
std::string plaintext;
plaintext.resize(ciphertext.size() - prefix_size);