mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-12-23 03:18:52 +00:00
Merge pull request #4103
bcab579
wallet: allow adjusting number of rounds for the key derivation function (stoffu)
This commit is contained in:
commit
017e07a035
@ -69,22 +69,26 @@ namespace crypto {
|
|||||||
chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher);
|
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");
|
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;
|
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
|
||||||
crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 0/*prehashed*/);
|
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));
|
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");
|
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;
|
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
|
||||||
crypto::cn_slow_hash(data, size, pwd_hash.data(), 0/*variant*/, 1/*prehashed*/);
|
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));
|
memcpy(&unwrap(key), pwd_hash.data(), sizeof(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void generate_chacha_key(std::string password, chacha_key& 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);
|
return generate_chacha_key(password.data(), password.size(), key, kdf_rounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ namespace hw {
|
|||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
virtual bool get_public_address(cryptonote::account_public_address &pubkey) = 0;
|
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 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 */
|
/* SUB ADDRESS */
|
||||||
|
@ -100,14 +100,14 @@ namespace hw {
|
|||||||
/* WALLET & ADDRESS */
|
/* 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 &view_key = keys.m_view_secret_key;
|
||||||
const crypto::secret_key &spend_key = keys.m_spend_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;
|
tools::scrubbed_arr<char, sizeof(view_key) + sizeof(spend_key) + 1> data;
|
||||||
memcpy(data.data(), &view_key, sizeof(view_key));
|
memcpy(data.data(), &view_key, sizeof(view_key));
|
||||||
memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key));
|
memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key));
|
||||||
data[sizeof(data) - 1] = CHACHA8_KEY_TAIL;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
bool device_default::get_public_address(cryptonote::account_public_address &pubkey) {
|
bool device_default::get_public_address(cryptonote::account_public_address &pubkey) {
|
||||||
|
@ -73,7 +73,7 @@ namespace hw {
|
|||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
bool get_public_address(cryptonote::account_public_address &pubkey) override;
|
bool get_public_address(cryptonote::account_public_address &pubkey) override;
|
||||||
bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) 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 */
|
/* SUB ADDRESS */
|
||||||
|
@ -531,20 +531,20 @@ namespace hw {
|
|||||||
return true;
|
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();
|
AUTO_LOCK_CMD();
|
||||||
|
|
||||||
#ifdef DEBUG_HWDEVICE
|
#ifdef DEBUG_HWDEVICE
|
||||||
crypto::chacha_key key_x;
|
crypto::chacha_key key_x;
|
||||||
cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
|
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
|
#endif
|
||||||
|
|
||||||
send_simple(INS_GET_CHACHA8_PREKEY);
|
send_simple(INS_GET_CHACHA8_PREKEY);
|
||||||
|
|
||||||
char prekey[200];
|
char prekey[200];
|
||||||
memmove(prekey, &this->buffer_recv[0], 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
|
#ifdef DEBUG_HWDEVICE
|
||||||
hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data());
|
hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data());
|
||||||
|
@ -156,7 +156,7 @@ namespace hw {
|
|||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
bool get_public_address(cryptonote::account_public_address &pubkey) override;
|
bool get_public_address(cryptonote::account_public_address &pubkey) override;
|
||||||
bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) 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;
|
||||||
|
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
|
@ -366,7 +366,7 @@ void Wallet::error(const std::string &category, const std::string &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////// WalletImpl implementation ////////////////////////
|
///////////////////////// WalletImpl implementation ////////////////////////
|
||||||
WalletImpl::WalletImpl(NetworkType nettype)
|
WalletImpl::WalletImpl(NetworkType nettype, bool restricted, uint64_t kdf_rounds)
|
||||||
:m_wallet(nullptr)
|
:m_wallet(nullptr)
|
||||||
, m_status(Wallet::Status_Ok)
|
, m_status(Wallet::Status_Ok)
|
||||||
, m_trustedDaemon(false)
|
, m_trustedDaemon(false)
|
||||||
@ -377,7 +377,7 @@ WalletImpl::WalletImpl(NetworkType nettype)
|
|||||||
, m_rebuildWalletCache(false)
|
, m_rebuildWalletCache(false)
|
||||||
, m_is_connected(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_history = new TransactionHistoryImpl(this);
|
||||||
m_wallet2Callback = new Wallet2CallbackImpl(this);
|
m_wallet2Callback = new Wallet2CallbackImpl(this);
|
||||||
m_wallet->callback(m_wallet2Callback);
|
m_wallet->callback(m_wallet2Callback);
|
||||||
|
@ -52,7 +52,7 @@ struct Wallet2CallbackImpl;
|
|||||||
class WalletImpl : public Wallet
|
class WalletImpl : public Wallet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WalletImpl(NetworkType nettype = MAINNET);
|
WalletImpl(NetworkType nettype = MAINNET, bool restricted = false, uint64_t kdf_rounds = 1);
|
||||||
~WalletImpl();
|
~WalletImpl();
|
||||||
bool create(const std::string &path, const std::string &password,
|
bool create(const std::string &path, const std::string &password,
|
||||||
const std::string &language);
|
const std::string &language);
|
||||||
|
@ -920,9 +920,10 @@ struct WalletManager
|
|||||||
* \param password Password of wallet file
|
* \param password Password of wallet file
|
||||||
* \param language Language to be used to generate electrum seed mnemonic
|
* \param language Language to be used to generate electrum seed mnemonic
|
||||||
* \param nettype Network type
|
* \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)
|
* \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
|
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);
|
return createWallet(path, password, language, testnet ? TESTNET : MAINNET);
|
||||||
@ -933,9 +934,10 @@ struct WalletManager
|
|||||||
* \param path Name of wallet file
|
* \param path Name of wallet file
|
||||||
* \param password Password of wallet file
|
* \param password Password of wallet file
|
||||||
* \param nettype Network type
|
* \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)
|
* \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
|
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
|
||||||
{
|
{
|
||||||
return openWallet(path, password, testnet ? TESTNET : MAINNET);
|
return openWallet(path, password, testnet ? TESTNET : MAINNET);
|
||||||
@ -948,10 +950,11 @@ struct WalletManager
|
|||||||
* \param mnemonic mnemonic (25 words electrum seed)
|
* \param mnemonic mnemonic (25 words electrum seed)
|
||||||
* \param nettype Network type
|
* \param nettype Network type
|
||||||
* \param restoreHeight restore from start height
|
* \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)
|
* \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,
|
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,
|
Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
|
||||||
bool testnet = false, uint64_t restoreHeight = 0) // deprecated
|
bool testnet = false, uint64_t restoreHeight = 0) // deprecated
|
||||||
{
|
{
|
||||||
@ -983,6 +986,7 @@ struct WalletManager
|
|||||||
* \param addressString public address
|
* \param addressString public address
|
||||||
* \param viewKeyString view key
|
* \param viewKeyString view key
|
||||||
* \param spendKeyString spend key (optional)
|
* \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)
|
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
|
||||||
*/
|
*/
|
||||||
virtual Wallet * createWalletFromKeys(const std::string &path,
|
virtual Wallet * createWalletFromKeys(const std::string &path,
|
||||||
@ -992,7 +996,8 @@ struct WalletManager
|
|||||||
uint64_t restoreHeight,
|
uint64_t restoreHeight,
|
||||||
const std::string &addressString,
|
const std::string &addressString,
|
||||||
const std::string &viewKeyString,
|
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,
|
Wallet * createWalletFromKeys(const std::string &path,
|
||||||
const std::string &password,
|
const std::string &password,
|
||||||
const std::string &language,
|
const std::string &language,
|
||||||
@ -1043,6 +1048,7 @@ struct WalletManager
|
|||||||
* \param deviceName Device name
|
* \param deviceName Device name
|
||||||
* \param restoreHeight restore from start height (0 sets to current height)
|
* \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 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)
|
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
|
||||||
*/
|
*/
|
||||||
virtual Wallet * createWalletFromDevice(const std::string &path,
|
virtual Wallet * createWalletFromDevice(const std::string &path,
|
||||||
@ -1050,7 +1056,8 @@ struct WalletManager
|
|||||||
NetworkType nettype,
|
NetworkType nettype,
|
||||||
const std::string &deviceName,
|
const std::string &deviceName,
|
||||||
uint64_t restoreHeight = 0,
|
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
|
* \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 keys_file_name - location of keys file
|
||||||
* @param password - password to verify
|
* @param password - password to verify
|
||||||
* @param no_spend_key - verify only view keys?
|
* @param no_spend_key - verify only view keys?
|
||||||
|
* @param kdf_rounds - number of rounds for key derivation function
|
||||||
* @return - true if password is correct
|
* @return - true if password is correct
|
||||||
*
|
*
|
||||||
* @note
|
* @note
|
||||||
* This function will fail when the wallet keys file is opened because the wallet program locks the keys file.
|
* 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.
|
* 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
|
* \brief findWallets - searches for the wallet files by given path name recursively
|
||||||
|
@ -50,16 +50,16 @@ namespace epee {
|
|||||||
namespace Monero {
|
namespace Monero {
|
||||||
|
|
||||||
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
|
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);
|
wallet->create(path, password, language);
|
||||||
return wallet;
|
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);
|
wallet->open(path, password);
|
||||||
//Refresh addressBook
|
//Refresh addressBook
|
||||||
wallet->addressBook()->refresh();
|
wallet->addressBook()->refresh();
|
||||||
@ -87,9 +87,10 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path,
|
|||||||
const std::string &password,
|
const std::string &password,
|
||||||
const std::string &mnemonic,
|
const std::string &mnemonic,
|
||||||
NetworkType nettype,
|
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){
|
if(restoreHeight > 0){
|
||||||
wallet->setRefreshFromBlockHeight(restoreHeight);
|
wallet->setRefreshFromBlockHeight(restoreHeight);
|
||||||
}
|
}
|
||||||
@ -104,9 +105,10 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
|
|||||||
uint64_t restoreHeight,
|
uint64_t restoreHeight,
|
||||||
const std::string &addressString,
|
const std::string &addressString,
|
||||||
const std::string &viewKeyString,
|
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){
|
if(restoreHeight > 0){
|
||||||
wallet->setRefreshFromBlockHeight(restoreHeight);
|
wallet->setRefreshFromBlockHeight(restoreHeight);
|
||||||
}
|
}
|
||||||
@ -119,9 +121,10 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
|
|||||||
NetworkType nettype,
|
NetworkType nettype,
|
||||||
const std::string &deviceName,
|
const std::string &deviceName,
|
||||||
uint64_t restoreHeight,
|
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){
|
if(restoreHeight > 0){
|
||||||
wallet->setRefreshFromBlockHeight(restoreHeight);
|
wallet->setRefreshFromBlockHeight(restoreHeight);
|
||||||
}
|
}
|
||||||
@ -159,9 +162,9 @@ bool WalletManagerImpl::walletExists(const std::string &path)
|
|||||||
return false;
|
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)
|
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
|
||||||
|
@ -39,13 +39,14 @@ class WalletManagerImpl : public WalletManager
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Wallet * createWallet(const std::string &path, const std::string &password,
|
Wallet * createWallet(const std::string &path, const std::string &password,
|
||||||
const std::string &language, 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) 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,
|
virtual Wallet * recoveryWallet(const std::string &path,
|
||||||
const std::string &password,
|
const std::string &password,
|
||||||
const std::string &mnemonic,
|
const std::string &mnemonic,
|
||||||
NetworkType nettype,
|
NetworkType nettype,
|
||||||
uint64_t restoreHeight) override;
|
uint64_t restoreHeight,
|
||||||
|
uint64_t kdf_rounds = 1) override;
|
||||||
virtual Wallet * createWalletFromKeys(const std::string &path,
|
virtual Wallet * createWalletFromKeys(const std::string &path,
|
||||||
const std::string &password,
|
const std::string &password,
|
||||||
const std::string &language,
|
const std::string &language,
|
||||||
@ -53,7 +54,8 @@ public:
|
|||||||
uint64_t restoreHeight,
|
uint64_t restoreHeight,
|
||||||
const std::string &addressString,
|
const std::string &addressString,
|
||||||
const std::string &viewKeyString,
|
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
|
// 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;
|
virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight) override;
|
||||||
// deprecated: use createWalletFromKeys(..., password, ...) instead
|
// deprecated: use createWalletFromKeys(..., password, ...) instead
|
||||||
@ -69,10 +71,11 @@ public:
|
|||||||
NetworkType nettype,
|
NetworkType nettype,
|
||||||
const std::string &deviceName,
|
const std::string &deviceName,
|
||||||
uint64_t restoreHeight = 0,
|
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;
|
virtual bool closeWallet(Wallet *wallet, bool store = true) override;
|
||||||
bool walletExists(const std::string &path) 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::vector<std::string> findWallets(const std::string &path) override;
|
||||||
std::string errorString() const override;
|
std::string errorString() const override;
|
||||||
void setDaemonAddress(const std::string &address) override;
|
void setDaemonAddress(const std::string &address) override;
|
||||||
|
@ -160,6 +160,7 @@ struct options {
|
|||||||
return val;
|
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)
|
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 bool stagenet = command_line::get_arg(vm, opts.stagenet);
|
||||||
const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
|
const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
|
||||||
const bool restricted = command_line::get_arg(vm, opts.restricted);
|
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_address = command_line::get_arg(vm, opts.daemon_address);
|
||||||
auto daemon_host = command_line::get_arg(vm, opts.daemon_host);
|
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())
|
if (daemon_address.empty())
|
||||||
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
|
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));
|
wallet->init(std::move(daemon_address), std::move(login));
|
||||||
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
|
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
|
||||||
wallet->set_ring_database(ringdb_path.string());
|
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;
|
constexpr const std::chrono::seconds wallet2::rpc_timeout;
|
||||||
const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); }
|
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_info(NULL),
|
||||||
m_multisig_rescan_k(NULL),
|
m_multisig_rescan_k(NULL),
|
||||||
m_run(true),
|
m_run(true),
|
||||||
@ -679,6 +682,7 @@ wallet2::wallet2(network_type nettype, bool restricted):
|
|||||||
m_ignore_fractional_outputs(true),
|
m_ignore_fractional_outputs(true),
|
||||||
m_is_initialized(false),
|
m_is_initialized(false),
|
||||||
m_restricted(restricted),
|
m_restricted(restricted),
|
||||||
|
m_kdf_rounds(kdf_rounds),
|
||||||
is_old_file_format(false),
|
is_old_file_format(false),
|
||||||
m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex),
|
m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex),
|
||||||
m_subaddress_lookahead_major(SUBADDRESS_LOOKAHEAD_MAJOR),
|
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.stagenet);
|
||||||
command_line::add_arg(desc_params, opts.restricted);
|
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.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)
|
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.
|
// Encrypt the entire JSON object.
|
||||||
crypto::chacha_key key;
|
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;
|
std::string cipher;
|
||||||
cipher.resize(account_data.size());
|
cipher.resize(account_data.size());
|
||||||
keys_file_data.iv = crypto::rand<crypto::chacha_iv>();
|
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);
|
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 + '\"');
|
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"');
|
||||||
crypto::chacha_key key;
|
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;
|
std::string account_data;
|
||||||
account_data.resize(keys_file_data.account_data.size());
|
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]);
|
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).
|
// this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded).
|
||||||
unlock_keys_file();
|
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();
|
lock_keys_file();
|
||||||
return r;
|
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
|
* 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;
|
rapidjson::Document json;
|
||||||
wallet2::keys_file_data keys_file_data;
|
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);
|
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 + '\"');
|
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"');
|
||||||
crypto::chacha_key key;
|
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;
|
std::string account_data;
|
||||||
account_data.resize(keys_file_data.account_data.size());
|
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]);
|
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
|
bool wallet2::generate_chacha_key_from_secret_keys(crypto::chacha_key &key) const
|
||||||
{
|
{
|
||||||
hw::device &hwdev = m_account.get_device();
|
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)
|
void wallet2::load(const std::string& wallet_, const epee::wipeable_string& password)
|
||||||
@ -10619,7 +10624,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
|
std::string wallet2::encrypt(const std::string &plaintext, const crypto::secret_key &skey, bool authenticated) const
|
||||||
{
|
{
|
||||||
crypto::chacha_key key;
|
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;
|
std::string ciphertext;
|
||||||
crypto::chacha_iv iv = crypto::rand<crypto::chacha_iv>();
|
crypto::chacha_iv iv = crypto::rand<crypto::chacha_iv>();
|
||||||
ciphertext.resize(plaintext.size() + sizeof(iv) + (authenticated ? sizeof(crypto::signature) : 0));
|
ciphertext.resize(plaintext.size() + sizeof(iv) + (authenticated ? sizeof(crypto::signature) : 0));
|
||||||
@ -10649,7 +10654,7 @@ std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret
|
|||||||
error::wallet_internal_error, "Unexpected ciphertext size");
|
error::wallet_internal_error, "Unexpected ciphertext size");
|
||||||
|
|
||||||
crypto::chacha_key key;
|
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];
|
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
|
||||||
std::string plaintext;
|
std::string plaintext;
|
||||||
plaintext.resize(ciphertext.size() - prefix_size);
|
plaintext.resize(ciphertext.size() - prefix_size);
|
||||||
|
@ -165,9 +165,9 @@ namespace tools
|
|||||||
//! Just parses variables.
|
//! 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 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();
|
~wallet2();
|
||||||
|
|
||||||
struct multisig_info
|
struct multisig_info
|
||||||
@ -1258,6 +1258,7 @@ namespace tools
|
|||||||
bool m_key_on_device;
|
bool m_key_on_device;
|
||||||
cryptonote::network_type m_nettype;
|
cryptonote::network_type m_nettype;
|
||||||
bool m_restricted;
|
bool m_restricted;
|
||||||
|
uint64_t m_kdf_rounds;
|
||||||
std::string seed_language; /*!< Language of the mnemonics (seed). */
|
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 is_old_file_format; /*!< Whether the wallet file is of an old file format */
|
||||||
bool m_watch_only; /*!< no spend key */
|
bool m_watch_only; /*!< no spend key */
|
||||||
|
@ -810,7 +810,7 @@ TEST(Serialization, portability_outputs)
|
|||||||
if(ciphertext.size() < prefix_size)
|
if(ciphertext.size() < prefix_size)
|
||||||
return {};
|
return {};
|
||||||
crypto::chacha_key key;
|
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];
|
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
|
||||||
std::string plaintext;
|
std::string plaintext;
|
||||||
plaintext.resize(ciphertext.size() - prefix_size);
|
plaintext.resize(ciphertext.size() - prefix_size);
|
||||||
|
Loading…
Reference in New Issue
Block a user