Skip to content

Commit

Permalink
wallet: allow adjusting number of rounds for the key derivation function
Browse files Browse the repository at this point in the history
  • Loading branch information
stoffu committed Aug 7, 2018
1 parent 0dddfea commit bcab579
Show file tree
Hide file tree
Showing 14 changed files with 76 additions and 52 deletions.
12 changes: 8 additions & 4 deletions src/crypto/chacha.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/device/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions src/device/device_default.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/device/device_default.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
6 changes: 3 additions & 3 deletions src/device/device_ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion src/device/device_ledger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;


/* ======================================================================= */
Expand Down
4 changes: 2 additions & 2 deletions src/wallet/api/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/api/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
20 changes: 14 additions & 6 deletions src/wallet/api/wallet2_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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
{
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -1043,14 +1048,16 @@ 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,
const std::string &password,
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
Expand All @@ -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
Expand Down
27 changes: 15 additions & 12 deletions src/wallet/api/wallet_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit bcab579

Please sign in to comment.