aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crypto/chacha.h12
-rw-r--r--src/device/device.hpp2
-rw-r--r--src/device/device_default.cpp4
-rw-r--r--src/device/device_default.hpp2
-rw-r--r--src/device/device_ledger.cpp6
-rw-r--r--src/device/device_ledger.hpp2
-rw-r--r--src/wallet/api/wallet.cpp4
-rw-r--r--src/wallet/api/wallet.h2
-rw-r--r--src/wallet/api/wallet2_api.h20
-rw-r--r--src/wallet/api/wallet_manager.cpp27
-rw-r--r--src/wallet/api/wallet_manager.h15
-rw-r--r--src/wallet/wallet2.cpp25
-rw-r--r--src/wallet/wallet2.h5
-rw-r--r--tests/unit_tests/serialization.cpp2
14 files changed, 76 insertions, 52 deletions
diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h
index 2b3ed8043..1dc270faf 100644
--- a/src/crypto/chacha.h
+++ b/src/crypto/chacha.h
@@ -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);
}
}
diff --git a/src/device/device.hpp b/src/device/device.hpp
index 9df0cb39d..c21456daf 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -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 */
diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp
index 0071f7d4f..bf14813ea 100644
--- a/src/device/device_default.cpp
+++ b/src/device/device_default.cpp
@@ -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) {
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index 771fbba72..8d841d9de 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -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 */
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index f7bf58531..7a34dad5e 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -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());
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index c30a38aca..e6c6e5b52 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -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;
/* ======================================================================= */
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 680da26ce..f7c074b5a 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -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);
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 58be686fc..28b73423d 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -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);
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 0cd0ff5cf..5a52c6b17 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -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
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 99eadc82f..5daf11ec0 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -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)
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 656a7142c..8b1c8be7f 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -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;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 90807803a..439bacd17 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -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);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 220eca8a8..e2c192084 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -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 */
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 5a2114027..40616059a 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -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);