diff options
author | Alexander Blair <snipa@jagtech.io> | 2020-08-16 12:39:58 -0700 |
---|---|---|
committer | Alexander Blair <snipa@jagtech.io> | 2020-08-16 12:39:59 -0700 |
commit | 6d29ee6c525dd1aa677e6a2a610f3aeb74fd23b2 (patch) | |
tree | 90237ee6130b0bcf2c22d3aba121bd944a062df5 /src/cryptonote_basic/account.cpp | |
parent | Merge pull request #6337 (diff) | |
parent | Use domain-separated ChaCha20 for in-memory key encryption (diff) | |
download | monero-6d29ee6c525dd1aa677e6a2a610f3aeb74fd23b2.tar.xz |
Merge pull request #6493
921dd8dde Use domain-separated ChaCha20 for in-memory key encryption (Sarang Noether)
Diffstat (limited to 'src/cryptonote_basic/account.cpp')
-rw-r--r-- | src/cryptonote_basic/account.cpp | 102 |
1 files changed, 61 insertions, 41 deletions
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 36ff41684..b366985ab 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -61,7 +61,8 @@ DISABLE_VS_WARNINGS(4244 4345) m_device = &hwdev; MCDEBUG("device", "account_keys::set_device device type: "<<typeid(hwdev).name()); } - //----------------------------------------------------------------- + + // Generate a derived chacha key static void derive_key(const crypto::chacha_key &base_key, crypto::chacha_key &key) { static_assert(sizeof(base_key) == sizeof(crypto::hash), "chacha key and hash should be the same size"); @@ -70,25 +71,38 @@ DISABLE_VS_WARNINGS(4244 4345) data[sizeof(base_key)] = config::HASH_KEY_MEMORY; crypto::generate_chacha_key(data.data(), sizeof(data), key, 1); } - //----------------------------------------------------------------- - static epee::wipeable_string get_key_stream(const crypto::chacha_key &base_key, const crypto::chacha_iv &iv, size_t bytes) + + // Prepare IVs and start chacha for encryption + void account_keys::encrypt_wrapper(const crypto::chacha_key &key, const bool all_keys) { - // derive a new key - crypto::chacha_key key; - derive_key(base_key, key); + // Set a fresh IV only for all-key encryption + if (all_keys) + m_encryption_iv = crypto::rand<crypto::chacha_iv>(); - // chacha - epee::wipeable_string buffer0(std::string(bytes, '\0')); - epee::wipeable_string buffer1 = buffer0; - crypto::chacha20(buffer0.data(), buffer0.size(), key, iv, buffer1.data()); - return buffer1; + // Now do the chacha + chacha_wrapper(key, all_keys); } - //----------------------------------------------------------------- - void account_keys::xor_with_key_stream(const crypto::chacha_key &key) + + // Start chacha for decryption + void account_keys::decrypt_wrapper(const crypto::chacha_key &key, const bool all_keys) + { + chacha_wrapper(key, all_keys); + } + + // Decrypt keys using the legacy method + void account_keys::decrypt_legacy(const crypto::chacha_key &key) { - // encrypt a large enough byte stream with chacha20 - epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * (2 + m_multisig_keys.size())); - const char *ptr = key_stream.data(); + // Derive domain-separated chacha key + crypto::chacha_key derived_key; + derive_key(key, derived_key); + + // Build key stream + epee::wipeable_string temp(std::string(sizeof(crypto::secret_key)*(2 + m_multisig_keys.size()), '\0')); + epee::wipeable_string stream = temp; + crypto::chacha20(temp.data(), temp.size(), derived_key, m_encryption_iv, stream.data()); + + // Decrypt all keys + const char *ptr = stream.data(); for (size_t i = 0; i < sizeof(crypto::secret_key); ++i) m_spend_secret_key.data[i] ^= *ptr++; for (size_t i = 0; i < sizeof(crypto::secret_key); ++i) @@ -99,33 +113,39 @@ DISABLE_VS_WARNINGS(4244 4345) k.data[i] ^= *ptr++; } } - //----------------------------------------------------------------- - void account_keys::encrypt(const crypto::chacha_key &key) + + // Perform chacha on either the view key or all keys + void account_keys::chacha_wrapper(const crypto::chacha_key &key, const bool all_keys) { - m_encryption_iv = crypto::rand<crypto::chacha_iv>(); - xor_with_key_stream(key); - } - //----------------------------------------------------------------- - void account_keys::decrypt(const crypto::chacha_key &key) - { - xor_with_key_stream(key); - } - //----------------------------------------------------------------- - void account_keys::encrypt_viewkey(const crypto::chacha_key &key) - { - // encrypt a large enough byte stream with chacha20 - epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * 2); - const char *ptr = key_stream.data(); - ptr += sizeof(crypto::secret_key); - for (size_t i = 0; i < sizeof(crypto::secret_key); ++i) - m_view_secret_key.data[i] ^= *ptr++; - } - //----------------------------------------------------------------- - void account_keys::decrypt_viewkey(const crypto::chacha_key &key) - { - encrypt_viewkey(key); + // Derive domain-seprated chacha key + crypto::chacha_key derived_key; + derive_key(key, derived_key); + + // Chacha the specified keys using the appropriate IVs + if (all_keys) + { + // Spend key + crypto::secret_key temp_key; + chacha20((char *) &m_spend_secret_key, sizeof(crypto::secret_key), derived_key, m_encryption_iv, (char *) &temp_key); + memcpy(&m_spend_secret_key, &temp_key, sizeof(crypto::secret_key)); + memwipe(&temp_key, sizeof(crypto::secret_key)); + + // Multisig keys + std::vector<crypto::secret_key> temp_keys; + temp_keys.reserve(m_multisig_keys.size()); + temp_keys.resize(m_multisig_keys.size()); + chacha20((char *) &m_multisig_keys[0], sizeof(crypto::secret_key)*m_multisig_keys.size(), derived_key, m_encryption_iv, (char *) &temp_keys[0]); + memcpy(&m_multisig_keys[0], &temp_keys[0], sizeof(crypto::secret_key)*temp_keys.size()); + memwipe(&temp_keys[0], sizeof(crypto::secret_key)*temp_keys.size()); + } + + // View key + crypto::secret_key temp_key; + chacha20((char *) &m_view_secret_key, sizeof(crypto::secret_key), derived_key, m_encryption_iv, (char *) &temp_key); + memcpy(&m_view_secret_key, &temp_key, sizeof(crypto::secret_key)); + memwipe(&temp_key, sizeof(crypto::secret_key)); } - //----------------------------------------------------------------- + account_base::account_base() { set_null(); |