wallet2: switch to chacha20 instead of chacha8

Wallet caches and keys files are loaded with chacha8 as needed,
but only saved with chacha20. Other data (eg, cold wallet data
files, etc) will be incompatible.
This commit is contained in:
moneromooo-monero 2017-12-07 19:17:32 +00:00
parent 1e5491e942
commit 5ad312a1c3
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3

View file

@ -2378,7 +2378,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
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>();
crypto::chacha8(account_data.data(), account_data.size(), key, keys_file_data.iv, &cipher[0]); crypto::chacha20(account_data.data(), account_data.size(), key, keys_file_data.iv, &cipher[0]);
keys_file_data.account_data = cipher; keys_file_data.account_data = cipher;
std::string buf; std::string buf;
@ -2406,6 +2406,7 @@ namespace
*/ */
bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_string& password) bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_string& password)
{ {
rapidjson::Document json;
wallet2::keys_file_data keys_file_data; wallet2::keys_file_data keys_file_data;
std::string buf; std::string buf;
bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf); bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
@ -2418,10 +2419,11 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
crypto::generate_chacha_key(password.data(), password.size(), key); crypto::generate_chacha_key(password.data(), password.size(), key);
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]);
if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
// The contents should be JSON if the wallet follows the new format. // The contents should be JSON if the wallet follows the new format.
rapidjson::Document json;
if (json.Parse(account_data.c_str()).HasParseError()) if (json.Parse(account_data.c_str()).HasParseError())
{ {
is_old_file_format = true; is_old_file_format = true;
@ -2591,6 +2593,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) const
*/ */
bool wallet2::verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key) bool wallet2::verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key)
{ {
rapidjson::Document json;
wallet2::keys_file_data keys_file_data; wallet2::keys_file_data keys_file_data;
std::string buf; std::string buf;
bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf); bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
@ -2603,10 +2606,11 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
crypto::generate_chacha_key(password.data(), password.size(), key); crypto::generate_chacha_key(password.data(), password.size(), key);
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]);
if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
// The contents should be JSON if the wallet follows the new format. // The contents should be JSON if the wallet follows the new format.
rapidjson::Document json;
if (json.Parse(account_data.c_str()).HasParseError()) if (json.Parse(account_data.c_str()).HasParseError())
{ {
// old format before JSON wallet key file format // old format before JSON wallet key file format
@ -3345,11 +3349,21 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
generate_chacha_key_from_secret_keys(key); generate_chacha_key_from_secret_keys(key);
std::string cache_data; std::string cache_data;
cache_data.resize(cache_file_data.cache_data.size()); cache_data.resize(cache_file_data.cache_data.size());
crypto::chacha8(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cache_data[0]); crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cache_data[0]);
try {
std::stringstream iss;
iss << cache_data;
boost::archive::portable_binary_iarchive ar(iss);
ar >> *this;
}
catch (...)
{
crypto::chacha8(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cache_data[0]);
try
{
std::stringstream iss; std::stringstream iss;
iss << cache_data; iss << cache_data;
try {
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> *this; ar >> *this;
} }
@ -3357,18 +3371,20 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{ {
LOG_PRINT_L0("Failed to open portable binary, trying unportable"); LOG_PRINT_L0("Failed to open portable binary, trying unportable");
boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists); boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
std::stringstream iss;
iss.str(""); iss.str("");
iss << cache_data; iss << cache_data;
boost::archive::binary_iarchive ar(iss); boost::archive::binary_iarchive ar(iss);
ar >> *this; ar >> *this;
} }
} }
}
catch (...) catch (...)
{ {
LOG_PRINT_L1("Failed to load encrypted cache, trying unencrypted"); LOG_PRINT_L1("Failed to load encrypted cache, trying unencrypted");
try {
std::stringstream iss; std::stringstream iss;
iss << buf; iss << buf;
try {
boost::archive::portable_binary_iarchive ar(iss); boost::archive::portable_binary_iarchive ar(iss);
ar >> *this; ar >> *this;
} }
@ -3376,6 +3392,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{ {
LOG_PRINT_L0("Failed to open portable binary, trying unportable"); LOG_PRINT_L0("Failed to open portable binary, trying unportable");
boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists); boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
std::stringstream iss;
iss.str(""); iss.str("");
iss << buf; iss << buf;
boost::archive::binary_iarchive ar(iss); boost::archive::binary_iarchive ar(iss);
@ -3505,7 +3522,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
std::string cipher; std::string cipher;
cipher.resize(cache_file_data.cache_data.size()); cipher.resize(cache_file_data.cache_data.size());
cache_file_data.iv = crypto::rand<crypto::chacha_iv>(); cache_file_data.iv = crypto::rand<crypto::chacha_iv>();
crypto::chacha8(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cipher[0]); crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cipher[0]);
cache_file_data.cache_data = cipher; cache_file_data.cache_data = cipher;
const std::string new_file = same_file ? m_wallet_file + ".new" : path; const std::string new_file = same_file ? m_wallet_file + ".new" : path;
@ -8725,7 +8742,7 @@ std::string wallet2::encrypt(const std::string &plaintext, const crypto::secret_
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));
crypto::chacha8(plaintext.data(), plaintext.size(), key, iv, &ciphertext[sizeof(iv)]); crypto::chacha20(plaintext.data(), plaintext.size(), key, iv, &ciphertext[sizeof(iv)]);
memcpy(&ciphertext[0], &iv, sizeof(iv)); memcpy(&ciphertext[0], &iv, sizeof(iv));
if (authenticated) if (authenticated)
{ {
@ -8765,7 +8782,7 @@ std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret
THROW_WALLET_EXCEPTION_IF(!crypto::check_signature(hash, pkey, signature), THROW_WALLET_EXCEPTION_IF(!crypto::check_signature(hash, pkey, signature),
error::wallet_internal_error, "Failed to authenticate ciphertext"); error::wallet_internal_error, "Failed to authenticate ciphertext");
} }
crypto::chacha8(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, &plaintext[0]); crypto::chacha20(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, &plaintext[0]);
return plaintext; return plaintext;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------