aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_basic')
-rw-r--r--src/cryptonote_basic/account.cpp66
-rw-r--r--src/cryptonote_basic/account.h16
2 files changed, 82 insertions, 0 deletions
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index aac6ec22b..0aebf9223 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -44,6 +44,9 @@ extern "C"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "account"
+#define KEYS_ENCRYPTION_SALT 'k'
+
+
using namespace std;
DISABLE_VS_WARNINGS(4244 4345)
@@ -60,7 +63,70 @@ DISABLE_VS_WARNINGS(4244 4345)
m_device = &hwdev;
MCDEBUG("device", "account_keys::set_device device type: "<<typeid(hwdev).name());
}
+ //-----------------------------------------------------------------
+ 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");
+ tools::scrubbed_arr<char, sizeof(base_key)+1> data;
+ memcpy(data.data(), &base_key, sizeof(base_key));
+ data[sizeof(base_key)] = KEYS_ENCRYPTION_SALT;
+ 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)
+ {
+ // derive a new key
+ crypto::chacha_key key;
+ derive_key(base_key, key);
+ // 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;
+ }
+ //-----------------------------------------------------------------
+ void account_keys::xor_with_key_stream(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();
+ 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)
+ m_view_secret_key.data[i] ^= *ptr++;
+ for (crypto::secret_key &k: m_multisig_keys)
+ {
+ for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
+ k.data[i] ^= *ptr++;
+ }
+ }
+ //-----------------------------------------------------------------
+ void account_keys::encrypt(const crypto::chacha_key &key)
+ {
+ 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);
+ }
//-----------------------------------------------------------------
account_base::account_base()
{
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
index b5d119c46..dac66ff1a 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -44,18 +44,29 @@ namespace cryptonote
crypto::secret_key m_view_secret_key;
std::vector<crypto::secret_key> m_multisig_keys;
hw::device *m_device = &hw::get_device("default");
+ crypto::chacha_iv m_encryption_iv;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_account_address)
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_secret_key)
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_secret_key)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_multisig_keys)
+ const crypto::chacha_iv default_iv{{0, 0, 0, 0, 0, 0, 0, 0}};
+ KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(m_encryption_iv, default_iv)
END_KV_SERIALIZE_MAP()
account_keys& operator=(account_keys const&) = default;
+ void encrypt(const crypto::chacha_key &key);
+ void decrypt(const crypto::chacha_key &key);
+ void encrypt_viewkey(const crypto::chacha_key &key);
+ void decrypt_viewkey(const crypto::chacha_key &key);
+
hw::device& get_device() const ;
void set_device( hw::device &hwdev) ;
+
+ private:
+ void xor_with_key_stream(const crypto::chacha_key &key);
};
/************************************************************************/
@@ -87,6 +98,11 @@ namespace cryptonote
void forget_spend_key();
const std::vector<crypto::secret_key> &get_multisig_keys() const { return m_keys.m_multisig_keys; }
+ void encrypt_keys(const crypto::chacha_key &key) { m_keys.encrypt(key); }
+ void decrypt_keys(const crypto::chacha_key &key) { m_keys.decrypt(key); }
+ void encrypt_viewkey(const crypto::chacha_key &key) { m_keys.encrypt_viewkey(key); }
+ void decrypt_viewkey(const crypto::chacha_key &key) { m_keys.decrypt_viewkey(key); }
+
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int /*ver*/)
{