366 lines
10 KiB
C++
366 lines
10 KiB
C++
// Copyright (c) 2012-2013 The Cryptonote developers
|
||
// Distributed under the MIT/X11 software license, see the accompanying
|
||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||
|
||
#include <exception>
|
||
|
||
#include "gtest/gtest.h"
|
||
|
||
#include "include_base_utils.h"
|
||
#include "currency_core/account.h"
|
||
#include "currency_core/currency_format_utils.h"
|
||
|
||
TEST(wallet_seed, store_restore_test)
|
||
{
|
||
for (size_t i = 0; i != 100; i++)
|
||
{
|
||
currency::account_base acc;
|
||
acc.generate();
|
||
auto seed_phrase = acc.get_seed_phrase("");
|
||
|
||
currency::account_base acc2;
|
||
bool r = acc2.restore_from_seed_phrase(seed_phrase, "");
|
||
ASSERT_TRUE(r);
|
||
|
||
if (memcmp(&acc2.get_keys(), &acc.get_keys(), sizeof(currency::account_keys)))
|
||
{
|
||
ASSERT_TRUE(false);
|
||
}
|
||
}
|
||
|
||
for (size_t i = 0; i != 100; i++)
|
||
{
|
||
currency::account_base acc;
|
||
acc.generate();
|
||
auto seed_phrase = acc.get_seed_phrase("");
|
||
|
||
currency::account_base acc2;
|
||
bool r = acc2.restore_from_seed_phrase(seed_phrase, "");
|
||
ASSERT_TRUE(r);
|
||
|
||
if (memcmp(&acc2.get_keys(), &acc.get_keys(), sizeof(currency::account_keys)))
|
||
{
|
||
ASSERT_TRUE(false);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
struct wallet_seed_entry
|
||
{
|
||
std::string seed_phrase;
|
||
std::string spend_secret_key;
|
||
std::string view_secret_key;
|
||
uint64_t timestamp;
|
||
bool auditable;
|
||
bool valid;
|
||
};
|
||
|
||
wallet_seed_entry wallet_seed_entries[] =
|
||
{
|
||
{
|
||
// legacy 24-word seed phrase -- invalid
|
||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew god",
|
||
"",
|
||
"",
|
||
0,
|
||
false,
|
||
false
|
||
},
|
||
{
|
||
// old-style 25-word seed phrase -- valid
|
||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew god",
|
||
"5e051454d7226b5734ebd64f754b57db4c655ecda00bd324f1b241d0b6381c0f",
|
||
"7dde5590fdf430568c00556ac2accf09da6cde9a29a4bc7d1cb6fd267130f006",
|
||
0,
|
||
false,
|
||
true
|
||
},
|
||
{
|
||
// old-style 25-word seed phrase -- valid
|
||
"conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation conversation",
|
||
"71162f207499bc16260957c36a6586bb931d54be33ff56b94d565dfedbb3c70e",
|
||
"8454372096986c457f4e7dceef2f39b6050c35d87b31d9c9eb8d37bf8f1f430f",
|
||
0,
|
||
false,
|
||
true
|
||
},
|
||
{
|
||
// old-style 25-word seed phrase -- invalid word
|
||
"dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew dew!",
|
||
"",
|
||
"",
|
||
0,
|
||
false,
|
||
false
|
||
},
|
||
{
|
||
// old-style 25-word seed phrase -- invalid word
|
||
"six six six six six six six six six sex six six six six six six six six six six six six six six six",
|
||
"",
|
||
"",
|
||
0,
|
||
false,
|
||
false
|
||
},
|
||
{
|
||
// new-style 26-word seed phrase -- invalid word
|
||
"six six six six six six six six six six six six six six six six six six six six six six six six six sex",
|
||
"",
|
||
"",
|
||
0,
|
||
false,
|
||
false
|
||
},
|
||
{
|
||
// new-style 26-word seed phrase -- invalid checksum
|
||
"six six six six six six six six six six six six six six six six six six six six six six six six six six",
|
||
"",
|
||
"",
|
||
0,
|
||
false,
|
||
false
|
||
},
|
||
{
|
||
// new-style 26-word seed phrase - valid
|
||
"six six six six six six six six six six six six six six six six six six six six six six six six six frown",
|
||
"F54F61E3B974AD86171AE4944205C7BD0395BD7845899CDA8B1FBC5C947BB402",
|
||
"A18715058BBD914959C3A735B2022E9AE1D04452BC1FAD9E63C53668B7F57907",
|
||
1922832000,
|
||
false,
|
||
true
|
||
},
|
||
{
|
||
// new-style 26-word seed phrase auditable - valid
|
||
"six six six six six six six six six six six six six six six six six six six six six six six six six grace",
|
||
"F54F61E3B974AD86171AE4944205C7BD0395BD7845899CDA8B1FBC5C947BB402",
|
||
"A18715058BBD914959C3A735B2022E9AE1D04452BC1FAD9E63C53668B7F57907",
|
||
1922832000,
|
||
true,
|
||
true
|
||
},
|
||
|
||
};
|
||
|
||
TEST(wallet_seed, basic_test)
|
||
{
|
||
for (size_t i = 0; i < sizeof wallet_seed_entries / sizeof wallet_seed_entries[0]; ++i)
|
||
{
|
||
const wallet_seed_entry& wse = wallet_seed_entries[i];
|
||
currency::account_base acc;
|
||
bool r = false;
|
||
try
|
||
{
|
||
r = acc.restore_from_seed_phrase(wse.seed_phrase, "");
|
||
if (r)
|
||
{
|
||
for (size_t j = 0; j != 100; j++)
|
||
{
|
||
//generate random password
|
||
std::string pass = epee::string_tools::pod_to_hex(crypto::cn_fast_hash(&j, sizeof(j)));
|
||
pass.resize(std::min(j, (size_t)40));
|
||
|
||
//get secured seed
|
||
std::string secured_seed = acc.get_seed_phrase(pass);
|
||
|
||
currency::account_base acc2{};
|
||
if (!pass.empty())
|
||
{
|
||
//try to restore it without password(should fail)
|
||
bool r_fail = acc2.restore_from_seed_phrase(secured_seed, "");
|
||
ASSERT_EQ(r_fail, false);
|
||
}
|
||
|
||
//try to restore it with wrong password
|
||
bool r_fake_pass = acc2.restore_from_seed_phrase(secured_seed, "fake_password");
|
||
if (r_fake_pass)
|
||
{
|
||
//accidentally checksumm matched(quite possible)
|
||
ASSERT_EQ(false, acc2.get_keys() == acc.get_keys());
|
||
}
|
||
|
||
//try to restore it from right password
|
||
currency::account_base acc3;
|
||
bool r_true_res = acc3.restore_from_seed_phrase(secured_seed, pass);
|
||
ASSERT_EQ(true, r_true_res);
|
||
r = acc3.get_keys() == acc.get_keys();
|
||
ASSERT_TRUE(r);
|
||
|
||
}
|
||
}
|
||
}
|
||
catch (...)
|
||
{
|
||
r = false;
|
||
}
|
||
ASSERT_EQ(r, wse.valid);
|
||
|
||
if (r)
|
||
{
|
||
if (wse.timestamp)
|
||
{
|
||
ASSERT_EQ(wse.timestamp, acc.get_createtime());
|
||
}
|
||
|
||
ASSERT_EQ(wse.auditable, acc.get_public_address().is_auditable());
|
||
|
||
// check keys
|
||
crypto::secret_key v, s;
|
||
ASSERT_TRUE(epee::string_tools::parse_tpod_from_hex_string(wse.spend_secret_key, s));
|
||
ASSERT_EQ(s, acc.get_keys().spend_secret_key);
|
||
|
||
ASSERT_TRUE(epee::string_tools::parse_tpod_from_hex_string(wse.view_secret_key, v));
|
||
ASSERT_EQ(v, acc.get_keys().view_secret_key);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
TEST(wallet_seed, word_from_timestamp)
|
||
{
|
||
//timestamp = 0; use_password = false
|
||
ASSERT_EQ("like", currency::get_word_from_timestamp(0, false));
|
||
|
||
// timestamp = 0; use_password = true
|
||
ASSERT_EQ("among", currency::get_word_from_timestamp(0, true));
|
||
|
||
// timestamp = WALLET_BRAIN_DATE_OFFSET = 1543622400; use_password = false
|
||
ASSERT_EQ("like", currency::get_word_from_timestamp(1543622400, false));
|
||
|
||
// timestamp = WALLET_BRAIN_DATE_OFFSET = 1543622400; use_password = true
|
||
ASSERT_EQ("among", currency::get_word_from_timestamp(1543622400, true));
|
||
|
||
// timestamp = WALLET_BRAIN_DATE_OFFSET - 1 = 1543622399; use_password = false
|
||
ASSERT_EQ("like", currency::get_word_from_timestamp(1543622399, false));
|
||
|
||
// timestamp = WALLET_BRAIN_DATE_OFFSET + 1 = 1543622401; use_password = false
|
||
ASSERT_EQ("like", currency::get_word_from_timestamp(1543622401, false));
|
||
|
||
// timestamp = WALLET_BRAIN_DATE_OFFSET + 1 = 1543622401; use_password = true
|
||
ASSERT_EQ("among", currency::get_word_from_timestamp(1543622401, true));
|
||
|
||
/*
|
||
Values get_word_from_timestamp(1, true),
|
||
get_word_from_timestamp(1543622401, true) must be equal.
|
||
*/
|
||
|
||
ASSERT_EQ("among", currency::get_word_from_timestamp(1, true));
|
||
ASSERT_EQ(currency::get_word_from_timestamp(1, true),
|
||
currency::get_word_from_timestamp(1543622401, true));
|
||
|
||
/*
|
||
2027462399 is the largest timestamp argument value under which the
|
||
inequality weeks_count < WALLET_BRAIN_DATE_MAX_WEEKS_COUNT is satisfied.
|
||
|
||
timestamp = 2027462399
|
||
date_offset = timestamp - WALLET_BRAIN_DATE_OFFSET = 483839999
|
||
weeks_count = date_offset / WALLET_BRAIN_DATE_QUANTUM = 799
|
||
WALLET_BRAIN_DATE_MAX_WEEKS_COUNT = 800
|
||
WALLET_BRAIN_DATE_QUANTUM = 604800
|
||
|
||
floor(483839999 / 604800) = 799
|
||
floor(483840000 / 604800) = 800
|
||
*/
|
||
|
||
// weeks_count_32 = 799; wordsArray[799] = "ugly"
|
||
ASSERT_EQ("ugly", currency::get_word_from_timestamp(2027462399, false));
|
||
|
||
// weeks_count_32 = 799 + 800 = 1599; wordsArray[1599] = "moan"
|
||
ASSERT_EQ("moan", currency::get_word_from_timestamp(2027462399, true));
|
||
|
||
/*
|
||
If you pass values >= 2027462399 + 1, then the inequality
|
||
weeks_count < WALLET_BRAIN_DATE_MAX_WEEKS_COUNT is not satisfied. The
|
||
function throws an exception.
|
||
*/
|
||
|
||
EXPECT_THROW(currency::get_word_from_timestamp(2027462400, false),
|
||
std::runtime_error);
|
||
|
||
EXPECT_THROW(currency::get_word_from_timestamp(2027462400, true),
|
||
std::runtime_error);
|
||
}
|
||
|
||
TEST(wallet_seed, timestamp_from_word)
|
||
{
|
||
{
|
||
// WALLET_BRAIN_DATE_OFFSET = 1543622400
|
||
|
||
{
|
||
bool password_used{false};
|
||
|
||
ASSERT_EQ(1543622400,
|
||
currency::get_timestamp_from_word("like", password_used));
|
||
ASSERT_FALSE(password_used);
|
||
}
|
||
|
||
{
|
||
bool password_used{true};
|
||
|
||
ASSERT_EQ(1543622400,
|
||
currency::get_timestamp_from_word("like", password_used));
|
||
ASSERT_FALSE(password_used);
|
||
}
|
||
}
|
||
|
||
{
|
||
// WALLET_BRAIN_DATE_OFFSET = 1543622400
|
||
|
||
{
|
||
bool password_used{true};
|
||
|
||
ASSERT_EQ(1543622400,
|
||
currency::get_timestamp_from_word("among", password_used));
|
||
ASSERT_TRUE(password_used);
|
||
}
|
||
|
||
{
|
||
bool password_used{false};
|
||
|
||
ASSERT_EQ(1543622400,
|
||
currency::get_timestamp_from_word("among", password_used));
|
||
ASSERT_TRUE(password_used);
|
||
}
|
||
}
|
||
|
||
{
|
||
// (1625 - 800) * 604800 + 1543622400 = 2042582400
|
||
|
||
{
|
||
bool password_used{false};
|
||
|
||
ASSERT_EQ(2026857600,
|
||
currency::get_timestamp_from_word("ugly", password_used));
|
||
ASSERT_FALSE(password_used);
|
||
}
|
||
|
||
{
|
||
bool password_used{true};
|
||
|
||
ASSERT_EQ(2026857600,
|
||
currency::get_timestamp_from_word("ugly", password_used));
|
||
ASSERT_FALSE(password_used);
|
||
}
|
||
}
|
||
|
||
{
|
||
// (1625 - 800) * 604800 + 1543622400 = 2042582400
|
||
|
||
{
|
||
bool password_used{false};
|
||
|
||
ASSERT_EQ(2042582400,
|
||
currency::get_timestamp_from_word("weary", password_used));
|
||
ASSERT_TRUE(password_used);
|
||
}
|
||
|
||
{
|
||
bool password_used{true};
|
||
|
||
ASSERT_EQ(2042582400,
|
||
currency::get_timestamp_from_word("weary", password_used));
|
||
ASSERT_TRUE(password_used);
|
||
}
|
||
}
|
||
}
|