Implement ElectrumWords::get_invalid_word

This commit is contained in:
b4n6-b4n6 2024-08-30 20:40:01 +07:00
parent a1dc85c537
commit 08b7fe4e92
4 changed files with 112 additions and 1 deletions

View File

@ -371,6 +371,59 @@ namespace crypto
return true; return true;
} }
std::string get_invalid_word(const epee::wipeable_string &words)
{
// If there's a new language added, add an instance of it here.
std::vector<Language::Base*> language_instances({
Language::Singleton<Language::Chinese_Simplified>::instance(),
Language::Singleton<Language::English>::instance(),
Language::Singleton<Language::Dutch>::instance(),
Language::Singleton<Language::French>::instance(),
Language::Singleton<Language::Spanish>::instance(),
Language::Singleton<Language::German>::instance(),
Language::Singleton<Language::Italian>::instance(),
Language::Singleton<Language::Portuguese>::instance(),
Language::Singleton<Language::Japanese>::instance(),
Language::Singleton<Language::Russian>::instance(),
Language::Singleton<Language::Esperanto>::instance(),
Language::Singleton<Language::Lojban>::instance(),
Language::Singleton<Language::EnglishOld>::instance()
});
std::vector<epee::wipeable_string> seed;
words.split(seed);
for (
std::vector<epee::wipeable_string>::const_iterator seed_i = seed.begin();
seed_i != seed.end();
seed_i++
)
{
bool has_any = false;
for (
std::vector<Language::Base*>::iterator lang_i = language_instances.begin();
lang_i != language_instances.end() && !has_any;
lang_i++
)
{
auto &word_map = (*lang_i)->get_word_map();
if (word_map.count(*seed_i) != 0)
{
has_any = true;
break;
}
}
if (!has_any) {
return std::string(seed_i->data(), seed_i->size());
}
}
return "";
}
/*! /*!
* \brief Converts bytes (secret key) to seed words. * \brief Converts bytes (secret key) to seed words.
* \param src Secret key * \param src Secret key

View File

@ -83,6 +83,8 @@ namespace crypto
bool words_to_bytes(const epee::wipeable_string &words, crypto::secret_key& dst, bool words_to_bytes(const epee::wipeable_string &words, crypto::secret_key& dst,
std::string &language_name); std::string &language_name);
std::string get_invalid_word(const epee::wipeable_string &words);
/*! /*!
* \brief Converts bytes to seed words. * \brief Converts bytes to seed words.
* \param src Secret data * \param src Secret data

View File

@ -749,7 +749,12 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
crypto::secret_key recovery_key; crypto::secret_key recovery_key;
std::string old_language; std::string old_language;
if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) { if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) {
setStatusError(tr("Electrum-style word list failed verification")); std::string invalid_word = crypto::ElectrumWords::get_invalid_word(seed);
if (invalid_word != "") {
setStatusError((boost::format(tr("Invalid word %s")) % ("'" + invalid_word + "'")).str());
} else {
setStatusError(tr("Electrum-style word list failed verification"));
}
return false; return false;
} }
if (!seed_offset.empty()) if (!seed_offset.empty())

View File

@ -255,3 +255,54 @@ TEST(mnemonics, partial_word_tolerance)
ASSERT_EQ(true, res); ASSERT_EQ(true, res);
ASSERT_STREQ(language_name_1.c_str(), "English"); ASSERT_STREQ(language_name_1.c_str(), "English");
} }
TEST(mnemonics, get_invalid_word)
{
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"crim bam scamp gna limi woma wron tuit birth mundane donuts square cohesive dolphin titans narrate fue saved wrap aloof magic mirr toget upda wra"
) == "crim"
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"criminal bamboo scamper gnaw limits womanly wrong tuition birth mundane donuts square cohesive dolphin titans narrate fue saved wrap aloof magically mirror together update wrap"
) == "fue"
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"a a a a a a a a a a a a a a a a a a a a a a a a a"
) == "a"
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandonnn abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"
) == "abandonnn"
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"abando abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandonnn abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"
) == "abando"
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"criminal bamboo scamper gnaw limits womanly wrong tuition birth mundane donuts square cohesive dolphin titans narrate fuel saved wrap aloof magically mirror together update wrap"
) == ""
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"
) == ""
);
ASSERT_TRUE(
crypto::ElectrumWords::get_invalid_word(
""
) == ""
);
}