secure seed: basic support implementation(in work)
This commit is contained in:
parent
d2899efbf1
commit
20631c5805
5 changed files with 71 additions and 20 deletions
|
|
@ -60,18 +60,42 @@ namespace currency
|
|||
return m_keys;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
std::string account_base::get_seed_phrase() const
|
||||
void crypt_with_pass(const void* scr_data, std::size_t src_length, void* dst_data, const std::string& password)
|
||||
{
|
||||
crypto::chacha8_key key = AUTO_VAL_INIT(key);
|
||||
crypto::generate_chacha8_key(password, key);
|
||||
crypto::hash pass_hash = crypto::cn_fast_hash(password.data(), password.size());
|
||||
crypto::chacha8_iv iv = AUTO_VAL_INIT(iv);
|
||||
CHECK_AND_ASSERT_THROW_MES(sizeof(pass_hash) >= sizeof(iv), "Invalid configuration: hash size is less than keys_file_data.iv");
|
||||
iv = *((crypto::chacha8_iv*)&pass_hash);
|
||||
crypto::chacha8(scr_data, src_length, key, iv, (char*)dst_data);
|
||||
}
|
||||
|
||||
|
||||
std::string account_base::get_seed_phrase(const std::string& password) const
|
||||
{
|
||||
if (m_keys_seed_binary.empty())
|
||||
return "";
|
||||
std::string keys_seed_text = tools::mnemonic_encoding::binary2text(m_keys_seed_binary);
|
||||
std::string timestamp_word = currency::get_word_from_timstamp(m_creation_timestamp);
|
||||
|
||||
std::vector<unsigned char> processed_seed_binary = m_keys_seed_binary;
|
||||
if (!password.empty())
|
||||
{
|
||||
//encrypt seed phrase binary data
|
||||
crypt_with_pass(&m_keys_seed_binary[0], m_keys_seed_binary.size(), &processed_seed_binary[0], password);
|
||||
}
|
||||
|
||||
std::string keys_seed_text = tools::mnemonic_encoding::binary2text(processed_seed_binary);
|
||||
std::string timestamp_word = currency::get_word_from_timstamp(m_creation_timestamp, !password.empty());
|
||||
|
||||
// floor creation time to WALLET_BRAIN_DATE_QUANTUM to make checksum calculation stable
|
||||
uint64_t creation_timestamp_rounded = get_timstamp_from_word(timestamp_word);
|
||||
bool self_check_is_password_used = false;
|
||||
uint64_t creation_timestamp_rounded = get_timstamp_from_word(timestamp_word, self_check_is_password_used);
|
||||
CHECK_AND_ASSERT_THROW_MES(self_check_is_password_used == !password.empty(), "Account seed phrase internal error: password flag encoded wrong");
|
||||
|
||||
constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum
|
||||
crypto::hash h = crypto::cn_fast_hash(m_keys_seed_binary.data(), m_keys_seed_binary.size());
|
||||
std::string binary_for_check_sum = m_keys_seed_binary;
|
||||
binary_for_check_sum.append(password);
|
||||
crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size());
|
||||
*reinterpret_cast<uint64_t*>(&h) = creation_timestamp_rounded;
|
||||
h = crypto::cn_fast_hash(&h, sizeof h);
|
||||
uint64_t h_64 = *reinterpret_cast<uint64_t*>(&h);
|
||||
|
|
@ -104,7 +128,7 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
bool account_base::restore_from_seed_phrase(const std::string& seed_phrase)
|
||||
bool account_base::restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password)
|
||||
{
|
||||
//cut the last timestamp word from restore_dats
|
||||
std::list<std::string> words;
|
||||
|
|
@ -138,9 +162,20 @@ namespace currency
|
|||
auditable_flag_and_checksum = tools::mnemonic_encoding::num_by_word(auditable_flag_and_checksum_word);
|
||||
|
||||
std::vector<unsigned char> keys_seed_binary = tools::mnemonic_encoding::text2binary(keys_seed_text);
|
||||
CHECK_AND_ASSERT_MES(keys_seed_binary.size(), false, "text2binary failed to convert the given text"); // don't prints event incorrect seed into the log for security
|
||||
std::vector<unsigned char> keys_seed_processed_binary = keys_seed_binary;
|
||||
|
||||
m_creation_timestamp = get_timstamp_from_word(timestamp_word);
|
||||
|
||||
bool has_password = false;
|
||||
m_creation_timestamp = get_timstamp_from_word(timestamp_word, has_password);
|
||||
//double check is password setting from timestamp word match with passed parameters
|
||||
CHECK_AND_ASSERT_MES(has_password != seed_password.empty(), false, "Seed phrase password wrong interpretation");
|
||||
if (has_password)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!seed_password.empty(), false, "Seed phrase password wrong interpretation: internal error");
|
||||
crypt_with_pass(&keys_seed_binary[0], keys_seed_binary.size(), &keys_seed_processed_binary[0], seed_password);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(keys_seed_processed_binary.size(), false, "text2binary failed to convert the given text"); // don't prints event incorrect seed into the log for security
|
||||
|
||||
bool auditable_flag = false;
|
||||
|
||||
|
|
@ -150,7 +185,9 @@ namespace currency
|
|||
auditable_flag = (auditable_flag_and_checksum & 1) != 0; // auditable flag is the lower 1 bit
|
||||
uint16_t checksum = static_cast<uint16_t>(auditable_flag_and_checksum >> 1); // checksum -- everything else
|
||||
constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum
|
||||
crypto::hash h = crypto::cn_fast_hash(keys_seed_binary.data(), keys_seed_binary.size());
|
||||
std::string binary_for_check_sum = keys_seed_processed_binary;
|
||||
binary_for_check_sum.append(seed_password);
|
||||
crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size());
|
||||
*reinterpret_cast<uint64_t*>(&h) = m_creation_timestamp;
|
||||
h = crypto::cn_fast_hash(&h, sizeof h);
|
||||
uint64_t h_64 = *reinterpret_cast<uint64_t*>(&h);
|
||||
|
|
@ -158,10 +195,10 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(checksum == checksum_calculated, false, "seed phase has invalid checksum: " << checksum_calculated << ", while " << checksum << " is expected, check your words");
|
||||
}
|
||||
|
||||
bool r = restore_keys(keys_seed_binary);
|
||||
bool r = restore_keys(keys_seed_processed_binary);
|
||||
CHECK_AND_ASSERT_MES(r, false, "restore_keys failed");
|
||||
|
||||
m_keys_seed_binary = keys_seed_binary;
|
||||
m_keys_seed_binary = keys_seed_processed_binary;
|
||||
|
||||
if (auditable_flag)
|
||||
m_keys.account_address.flags |= ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE;
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ namespace currency
|
|||
const account_public_address& get_public_address() const { return m_keys.account_address; };
|
||||
std::string get_public_address_str() const;
|
||||
|
||||
std::string get_seed_phrase() const;
|
||||
std::string get_seed_phrase(const std::string& seed_password) const;
|
||||
std::string get_tracking_seed() const;
|
||||
bool restore_from_seed_phrase(const std::string& seed_phrase);
|
||||
bool restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password);
|
||||
bool restore_from_tracking_seed(const std::string& tracking_seed);
|
||||
|
||||
uint64_t get_createtime() const { return m_creation_timestamp; }
|
||||
|
|
|
|||
|
|
@ -150,9 +150,10 @@
|
|||
|
||||
#define WALLET_FILE_MAX_KEYS_SIZE 10000 //
|
||||
#define WALLET_BRAIN_DATE_OFFSET 1543622400
|
||||
#define WALLET_BRAIN_DATE_QUANTUM 604800 //by last word we encode a number of week since launch of the project,
|
||||
#define WALLET_BRAIN_DATE_QUANTUM 604800 //by last word we encode a number of week since launch of the project AND password flag,
|
||||
//which let us to address tools::mnemonic_encoding::NUMWORDS weeks after project launch
|
||||
//which is about 30 years
|
||||
//which is about 15 years
|
||||
#define WALLET_BRAIN_DATE_MAX_WEEKS_COUNT 800
|
||||
|
||||
#define OFFER_MAXIMUM_LIFE_TIME (60*60*24*30) // 30 days
|
||||
|
||||
|
|
|
|||
|
|
@ -1316,21 +1316,34 @@ namespace currency
|
|||
return reward;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string get_word_from_timstamp(uint64_t timestamp)
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password)
|
||||
{
|
||||
uint64_t date_offset = timestamp > WALLET_BRAIN_DATE_OFFSET ? timestamp - WALLET_BRAIN_DATE_OFFSET : 0;
|
||||
uint64_t weeks_count = date_offset / WALLET_BRAIN_DATE_QUANTUM;
|
||||
CHECK_AND_ASSERT_THROW_MES(weeks_count < WALLET_BRAIN_DATE_MAX_WEEKS_COUNT, "SEED PHRASE need to be extended or refactored");
|
||||
|
||||
if (use_password)
|
||||
weeks_count += WALLET_BRAIN_DATE_MAX_WEEKS_COUNT;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(weeks_count < std::numeric_limits<uint32_t>::max(), "internal error: unable to convert to uint32, val = " << weeks_count);
|
||||
uint32_t weeks_count_32 = static_cast<uint32_t>(weeks_count);
|
||||
|
||||
return tools::mnemonic_encoding::word_by_num(weeks_count_32);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_timstamp_from_word(std::string word)
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used)
|
||||
{
|
||||
uint64_t count_of_weeks = tools::mnemonic_encoding::num_by_word(word);
|
||||
if (count_of_weeks > WALLET_BRAIN_DATE_MAX_WEEKS_COUNT)
|
||||
{
|
||||
count_of_weeks -= WALLET_BRAIN_DATE_MAX_WEEKS_COUNT;
|
||||
password_used = true;
|
||||
}
|
||||
else {
|
||||
password_used = false;
|
||||
}
|
||||
uint64_t timestamp = count_of_weeks * WALLET_BRAIN_DATE_QUANTUM + WALLET_BRAIN_DATE_OFFSET;
|
||||
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -291,8 +291,8 @@ namespace currency
|
|||
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false);
|
||||
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
|
||||
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp);
|
||||
uint64_t get_timstamp_from_word(std::string word);
|
||||
std::string get_word_from_timstamp(uint64_t timestamp, bool use_password);
|
||||
uint64_t get_timstamp_from_word(std::string word, bool& password_used);
|
||||
|
||||
template<class t_txin_v>
|
||||
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue