aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2014-10-15 12:14:44 +0200
committerRiccardo Spagni <ric@spagni.net>2014-10-15 12:14:49 +0200
commitdb5ca73fdde97ed680ef538034fb5210b45a43d4 (patch)
tree4b6d29ec984b3d7a2b06e5264249b065e71f01d8 /src
parentMerge pull request #174 (diff)
parentAdded unit test. Fails for Japanese for some reason. (diff)
downloadmonero-db5ca73fdde97ed680ef538034fb5210b45a43d4.tar.xz
Merge pull request #176
b94b8cd Added unit test. Fails for Japanese for some reason. (Oran Juice) 4c8a628 Remove iostream header put in during testing (Oran Juice) 9875f5b Variable unique prefix lengths for seed (Oran Juice)
Diffstat (limited to 'src')
-rw-r--r--src/mnemonics/electrum-words.cpp82
-rw-r--r--src/mnemonics/electrum-words.h3
-rw-r--r--src/mnemonics/english.h1
-rw-r--r--src/mnemonics/japanese.h1
-rw-r--r--src/mnemonics/language_base.h8
-rw-r--r--src/mnemonics/old_english.h1
-rw-r--r--src/mnemonics/portuguese.h1
-rw-r--r--src/mnemonics/spanish.h1
8 files changed, 48 insertions, 50 deletions
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp
index b204e81cf..ffa82b21e 100644
--- a/src/mnemonics/electrum-words.cpp
+++ b/src/mnemonics/electrum-words.cpp
@@ -61,7 +61,6 @@
namespace
{
- const int seed_length = 24;
/*!
* \brief Finds the word list that contains the seed words and puts the indices
@@ -69,11 +68,11 @@ namespace
* \param seed List of words to match.
* \param has_checksum If word list passed checksum test, we need to only do a prefix check.
* \param matched_indices The indices where the seed words were found are added to this.
+ * \param language Language instance pointer to write to after it is found.
* \return true if all the words were present in some language false if not.
*/
bool find_seed_language(const std::vector<std::string> &seed,
- bool has_checksum, std::vector<uint32_t> &matched_indices, uint32_t &word_list_length,
- std::string &language_name)
+ bool has_checksum, std::vector<uint32_t> &matched_indices, Language::Base **language)
{
// If there's a new language added, add an instance of it here.
std::vector<Language::Base*> language_instances({
@@ -83,18 +82,6 @@ namespace
Language::Singleton<Language::Japanese>::instance(),
Language::Singleton<Language::OldEnglish>::instance()
});
- // To hold trimmed seed words in case of a checksum being present.
- std::vector<std::string> trimmed_seed;
- if (has_checksum)
- {
- // If it had a checksum, we'll just compare the unique prefix
- // So we create a list of trimmed seed words
- for (std::vector<std::string>::const_iterator it = seed.begin(); it != seed.end(); it++)
- {
- trimmed_seed.push_back(it->length() > Language::unique_prefix_length ?
- it->substr(0, Language::unique_prefix_length) : *it);
- }
- }
// Iterate through all the languages and find a match
for (std::vector<Language::Base*>::iterator it1 = language_instances.begin();
@@ -104,23 +91,22 @@ namespace
const std::unordered_map<std::string, uint32_t> &trimmed_word_map = (*it1)->get_trimmed_word_map();
// To iterate through seed words
std::vector<std::string>::const_iterator it2;
- // To iterate through trimmed seed words
- std::vector<std::string>::iterator it3;
bool full_match = true;
+ std::string trimmed_word;
// Iterate through all the words and see if they're all present
- for (it2 = seed.begin(), it3 = trimmed_seed.begin();
- it2 != seed.end(); it2++, it3++)
+ for (it2 = seed.begin(); it2 != seed.end(); it2++)
{
if (has_checksum)
{
+ trimmed_word = it2->substr(0, (*it1)->get_unique_prefix_length());
// Use the trimmed words and map
- if (trimmed_word_map.count(*it3) == 0)
+ if (trimmed_word_map.count(trimmed_word) == 0)
{
full_match = false;
break;
}
- matched_indices.push_back(trimmed_word_map.at(*it3));
+ matched_indices.push_back(trimmed_word_map.at(trimmed_word));
}
else
{
@@ -134,8 +120,7 @@ namespace
}
if (full_match)
{
- word_list_length = (*it1)->get_word_list().size();
- language_name = (*it1)->get_language_name();
+ *language = *it1;
return true;
}
// Some didn't match. Clear the index array.
@@ -146,18 +131,20 @@ namespace
/*!
* \brief Creates a checksum index in the word list array on the list of words.
- * \param word_list Vector of words
- * \return Checksum index
+ * \param word_list Vector of words
+ * \param unique_prefix_length the prefix length of each word to use for checksum
+ * \return Checksum index
*/
- uint32_t create_checksum_index(const std::vector<std::string> &word_list)
+ uint32_t create_checksum_index(const std::vector<std::string> &word_list,
+ uint32_t unique_prefix_length)
{
std::string trimmed_words = "";
for (std::vector<std::string>::const_iterator it = word_list.begin(); it != word_list.end(); it++)
{
- if (it->length() > 4)
+ if (it->length() > unique_prefix_length)
{
- trimmed_words += it->substr(0, Language::unique_prefix_length);
+ trimmed_words += it->substr(0, unique_prefix_length);
}
else
{
@@ -166,25 +153,26 @@ namespace
}
boost::crc_32_type result;
result.process_bytes(trimmed_words.data(), trimmed_words.length());
- return result.checksum() % seed_length;
+ return result.checksum() % crypto::ElectrumWords::seed_length;
}
/*!
* \brief Does the checksum test on the seed passed.
- * \param seed Vector of seed words
- * \return True if the test passed false if not.
+ * \param seed Vector of seed words
+ * \param unique_prefix_length the prefix length of each word to use for checksum
+ * \return True if the test passed false if not.
*/
- bool checksum_test(std::vector<std::string> seed)
+ bool checksum_test(std::vector<std::string> seed, uint32_t unique_prefix_length)
{
// The last word is the checksum.
std::string last_word = seed.back();
seed.pop_back();
- std::string checksum = seed[create_checksum_index(seed)];
+ std::string checksum = seed[create_checksum_index(seed, unique_prefix_length)];
- std::string trimmed_checksum = checksum.length() > 4 ? checksum.substr(0, Language::unique_prefix_length) :
+ std::string trimmed_checksum = checksum.length() > unique_prefix_length ? checksum.substr(0, unique_prefix_length) :
checksum;
- std::string trimmed_last_word = checksum.length() > 4 ? last_word.substr(0, Language::unique_prefix_length) :
+ std::string trimmed_last_word = last_word.length() > unique_prefix_length ? last_word.substr(0, unique_prefix_length) :
last_word;
return trimmed_checksum == trimmed_last_word;
}
@@ -211,11 +199,12 @@ namespace crypto
* \param language_name Language of the seed as found gets written here.
* \return false if not a multiple of 3 words, or if word is not in the words list
*/
- bool words_to_bytes(const std::string& words, crypto::secret_key& dst,
+ bool words_to_bytes(std::string words, crypto::secret_key& dst,
std::string &language_name)
{
std::vector<std::string> seed;
+ boost::algorithm::trim(words);
boost::split(seed, words, boost::is_any_of(" "));
// error on non-compliant word list
@@ -227,22 +216,25 @@ namespace crypto
// If it is seed with a checksum.
bool has_checksum = seed.size() == (seed_length + 1);
+
+ std::vector<uint32_t> matched_indices;
+ Language::Base *language;
+ if (!find_seed_language(seed, has_checksum, matched_indices, &language))
+ {
+ return false;
+ }
+ language_name = language->get_language_name();
+ uint32_t word_list_length = language->get_word_list().size();
+
if (has_checksum)
{
- if (!checksum_test(seed))
+ if (!checksum_test(seed, language->get_unique_prefix_length()))
{
// Checksum fail
return false;
}
seed.pop_back();
}
-
- std::vector<uint32_t> matched_indices;
- uint32_t word_list_length = 0;
- if (!find_seed_language(seed, has_checksum, matched_indices, word_list_length, language_name))
- {
- return false;
- }
for (unsigned int i=0; i < seed.size() / 3; i++)
{
@@ -335,7 +327,7 @@ namespace crypto
}
words.pop_back();
- words += (' ' + words_store[create_checksum_index(words_store)]);
+ words += (' ' + words_store[create_checksum_index(words_store, language->get_unique_prefix_length())]);
return false;
}
diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h
index b822e7740..b75de30e9 100644
--- a/src/mnemonics/electrum-words.h
+++ b/src/mnemonics/electrum-words.h
@@ -59,6 +59,7 @@ namespace crypto
namespace ElectrumWords
{
+ const int seed_length = 24;
const std::string old_language_name = "OldEnglish";
/*!
* \brief Converts seed words to bytes (secret key).
@@ -67,7 +68,7 @@ namespace crypto
* \param language_name Language of the seed as found gets written here.
* \return false if not a multiple of 3 words, or if word is not in the words list
*/
- bool words_to_bytes(const std::string& words, crypto::secret_key& dst,
+ bool words_to_bytes(std::string words, crypto::secret_key& dst,
std::string &language_name);
/*!
diff --git a/src/mnemonics/english.h b/src/mnemonics/english.h
index ae39d44fd..8ca0a3fe3 100644
--- a/src/mnemonics/english.h
+++ b/src/mnemonics/english.h
@@ -1681,6 +1681,7 @@ namespace Language
"zones",
"zoom"
});
+ unique_prefix_length = 3;
word_map = new std::unordered_map<std::string, uint32_t>;
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
language_name = "English";
diff --git a/src/mnemonics/japanese.h b/src/mnemonics/japanese.h
index 22c7a53ba..fc3d1ee74 100644
--- a/src/mnemonics/japanese.h
+++ b/src/mnemonics/japanese.h
@@ -1681,6 +1681,7 @@ namespace Language
"びじゅつかん",
"ひしょ"
});
+ unique_prefix_length = 4;
word_map = new std::unordered_map<std::string, uint32_t>;
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
language_name = "Japanese";
diff --git a/src/mnemonics/language_base.h b/src/mnemonics/language_base.h
index 0f1062b09..06815e39d 100644
--- a/src/mnemonics/language_base.h
+++ b/src/mnemonics/language_base.h
@@ -45,7 +45,6 @@
*/
namespace Language
{
- const int unique_prefix_length = 4; /*!< Length of the prefix of all words guaranteed to be unique */
/*!
* \class Base
* \brief A base language class which all languages have to inherit from for
@@ -58,7 +57,7 @@ namespace Language
std::unordered_map<std::string, uint32_t> *word_map; /*!< hash table to find word's index */
std::unordered_map<std::string, uint32_t> *trimmed_word_map; /*!< hash table to find word's trimmed index */
std::string language_name; /*!< Name of language */
- int trim_length; /*!< Number of unique starting characters to trim the wordlist to when matching */
+ uint32_t unique_prefix_length; /*!< Number of unique starting characters to trim the wordlist to when matching */
/*!
* \brief Populates the word maps after the list is ready.
*/
@@ -85,6 +84,7 @@ namespace Language
word_list = new std::vector<std::string>;
word_map = new std::unordered_map<std::string, uint32_t>;
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
+ unique_prefix_length = 4;
}
/*!
* \brief Returns a pointer to the word list.
@@ -122,9 +122,9 @@ namespace Language
* \brief Returns the number of unique starting characters to be used for matching.
* \return Number of unique starting characters.
*/
- int get_trim_length() const
+ uint32_t get_unique_prefix_length() const
{
- return trim_length;
+ return unique_prefix_length;
}
};
}
diff --git a/src/mnemonics/old_english.h b/src/mnemonics/old_english.h
index 09ac37e66..b91a593b6 100644
--- a/src/mnemonics/old_english.h
+++ b/src/mnemonics/old_english.h
@@ -1681,6 +1681,7 @@ namespace Language
"weapon",
"weary"
});
+ unique_prefix_length = 4;
word_map = new std::unordered_map<std::string, uint32_t>;
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
language_name = "OldEnglish";
diff --git a/src/mnemonics/portuguese.h b/src/mnemonics/portuguese.h
index c040a0415..6a90659e0 100644
--- a/src/mnemonics/portuguese.h
+++ b/src/mnemonics/portuguese.h
@@ -1679,6 +1679,7 @@ namespace Language
"zenite",
"zumbi"
});
+ unique_prefix_length = 4;
word_map = new std::unordered_map<std::string, uint32_t>;
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
language_name = "Portuguese";
diff --git a/src/mnemonics/spanish.h b/src/mnemonics/spanish.h
index 8d695a4b1..f71627086 100644
--- a/src/mnemonics/spanish.h
+++ b/src/mnemonics/spanish.h
@@ -1681,6 +1681,7 @@ namespace Language
"ritmo",
"rito"
});
+ unique_prefix_length = 4;
word_map = new std::unordered_map<std::string, uint32_t>;
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
language_name = "Spanish";