mnemonics: support for arbitrary (if multiple of 4 bytes) length data
This commit is contained in:
parent
3dd31d33fa
commit
2d1ccc1b88
|
@ -236,11 +236,13 @@ namespace crypto
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts seed words to bytes (secret key).
|
* \brief Converts seed words to bytes (secret key).
|
||||||
* \param words String containing the words separated by spaces.
|
* \param words String containing the words separated by spaces.
|
||||||
* \param dst To put the secret key restored from the words.
|
* \param dst To put the secret data restored from the words.
|
||||||
|
* \param len The number of bytes to expect, 0 if unknown
|
||||||
|
* \param duplicate If true and len is not zero, we accept half the data, and duplicate it
|
||||||
* \param language_name Language of the seed as found gets written here.
|
* \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
|
* \return false if not a multiple of 3 words, or if word is not in the words list
|
||||||
*/
|
*/
|
||||||
bool words_to_bytes(std::string words, crypto::secret_key& dst,
|
bool words_to_bytes(std::string words, std::string& dst, size_t len, bool duplicate,
|
||||||
std::string &language_name)
|
std::string &language_name)
|
||||||
{
|
{
|
||||||
std::vector<std::string> seed;
|
std::vector<std::string> seed;
|
||||||
|
@ -248,15 +250,23 @@ namespace crypto
|
||||||
boost::algorithm::trim(words);
|
boost::algorithm::trim(words);
|
||||||
boost::split(seed, words, boost::is_any_of(" "), boost::token_compress_on);
|
boost::split(seed, words, boost::is_any_of(" "), boost::token_compress_on);
|
||||||
|
|
||||||
// error on non-compliant word list
|
if (len % 4)
|
||||||
if (seed.size() != seed_length/2 && seed.size() != seed_length &&
|
|
||||||
seed.size() != seed_length + 1)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// If it is seed with a checksum.
|
bool has_checksum = true;
|
||||||
bool has_checksum = seed.size() == (seed_length + 1);
|
if (len)
|
||||||
|
{
|
||||||
|
// error on non-compliant word list
|
||||||
|
const size_t expected = len * 8 * 3 / 32;
|
||||||
|
if (seed.size() != expected/2 && seed.size() != expected &&
|
||||||
|
seed.size() != expected + 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is seed with a checksum.
|
||||||
|
has_checksum = seed.size() == (expected + 1);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> matched_indices;
|
std::vector<uint32_t> matched_indices;
|
||||||
Language::Base *language;
|
Language::Base *language;
|
||||||
|
@ -290,20 +300,43 @@ namespace crypto
|
||||||
|
|
||||||
if (!(val % word_list_length == w1)) return false;
|
if (!(val % word_list_length == w1)) return false;
|
||||||
|
|
||||||
memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position
|
dst.append((const char*)&val, 4); // copy 4 bytes to position
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string wlist_copy = words;
|
if (len > 0 && duplicate)
|
||||||
if (seed.size() == seed_length/2)
|
|
||||||
{
|
{
|
||||||
memcpy(dst.data+16, dst.data, 16); // if electrum 12-word seed, duplicate
|
const size_t expected = len * 3 / 32;
|
||||||
wlist_copy += ' ';
|
std::string wlist_copy = words;
|
||||||
wlist_copy += words;
|
if (seed.size() == expected/2)
|
||||||
|
{
|
||||||
|
dst.append(dst); // if electrum 12-word seed, duplicate
|
||||||
|
wlist_copy += ' ';
|
||||||
|
wlist_copy += words;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts seed words to bytes (secret key).
|
||||||
|
* \param words String containing the words separated by spaces.
|
||||||
|
* \param dst To put the secret key restored from the words.
|
||||||
|
* \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(std::string words, crypto::secret_key& dst,
|
||||||
|
std::string &language_name)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
if (!words_to_bytes(words, s, sizeof(dst), true, language_name))
|
||||||
|
return false;
|
||||||
|
if (s.size() != sizeof(dst))
|
||||||
|
return false;
|
||||||
|
dst = *(const crypto::secret_key*)s.data();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts bytes (secret key) to seed words.
|
* \brief Converts bytes (secret key) to seed words.
|
||||||
* \param src Secret key
|
* \param src Secret key
|
||||||
|
@ -311,11 +344,11 @@ namespace crypto
|
||||||
* \param language_name Seed language name
|
* \param language_name Seed language name
|
||||||
* \return true if successful false if not. Unsuccessful if wrong key size.
|
* \return true if successful false if not. Unsuccessful if wrong key size.
|
||||||
*/
|
*/
|
||||||
bool bytes_to_words(const crypto::secret_key& src, std::string& words,
|
bool bytes_to_words(const char *src, size_t len, std::string& words,
|
||||||
const std::string &language_name)
|
const std::string &language_name)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (sizeof(src.data) % 4 != 0 || sizeof(src.data) == 0) return false;
|
if (len % 4 != 0 || len == 0) return false;
|
||||||
|
|
||||||
Language::Base *language;
|
Language::Base *language;
|
||||||
if (language_name == "English")
|
if (language_name == "English")
|
||||||
|
@ -376,13 +409,13 @@ namespace crypto
|
||||||
|
|
||||||
uint32_t word_list_length = word_list.size();
|
uint32_t word_list_length = word_list.size();
|
||||||
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
|
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
|
||||||
for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
|
for (unsigned int i=0; i < len/4; i++, words += ' ')
|
||||||
{
|
{
|
||||||
uint32_t w1, w2, w3;
|
uint32_t w1, w2, w3;
|
||||||
|
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
memcpy(&val, (src.data) + (i * 4), 4);
|
memcpy(&val, src + (i * 4), 4);
|
||||||
|
|
||||||
w1 = val % word_list_length;
|
w1 = val % word_list_length;
|
||||||
w2 = ((val / word_list_length) + w1) % word_list_length;
|
w2 = ((val / word_list_length) + w1) % word_list_length;
|
||||||
|
@ -404,6 +437,12 @@ namespace crypto
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bytes_to_words(const crypto::secret_key& src, std::string& words,
|
||||||
|
const std::string &language_name)
|
||||||
|
{
|
||||||
|
return bytes_to_words(src.data, sizeof(src), words, language_name);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets a list of seed languages that are supported.
|
* \brief Gets a list of seed languages that are supported.
|
||||||
* \param languages The vector is set to the list of languages.
|
* \param languages The vector is set to the list of languages.
|
||||||
|
|
|
@ -61,6 +61,17 @@ namespace crypto
|
||||||
|
|
||||||
const int seed_length = 24;
|
const int seed_length = 24;
|
||||||
const std::string old_language_name = "EnglishOld";
|
const std::string old_language_name = "EnglishOld";
|
||||||
|
/*!
|
||||||
|
* \brief Converts seed words to bytes (secret key).
|
||||||
|
* \param words String containing the words separated by spaces.
|
||||||
|
* \param dst To put the secret data restored from the words.
|
||||||
|
* \param len The number of bytes to expect, 0 if unknown
|
||||||
|
* \param duplicate If true and len is not zero, we accept half the data, and duplicate it
|
||||||
|
* \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(std::string words, std::string& dst, size_t len, bool duplicate,
|
||||||
|
std::string &language_name);
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts seed words to bytes (secret key).
|
* \brief Converts seed words to bytes (secret key).
|
||||||
* \param words String containing the words separated by spaces.
|
* \param words String containing the words separated by spaces.
|
||||||
|
@ -71,6 +82,17 @@ namespace crypto
|
||||||
bool words_to_bytes(std::string words, crypto::secret_key& dst,
|
bool words_to_bytes(std::string words, crypto::secret_key& dst,
|
||||||
std::string &language_name);
|
std::string &language_name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Converts bytes to seed words.
|
||||||
|
* \param src Secret data
|
||||||
|
* \param len Secret data length in bytes (positive multiples of 4 only)
|
||||||
|
* \param words Space delimited concatenated words get written here.
|
||||||
|
* \param language_name Seed language name
|
||||||
|
* \return true if successful false if not. Unsuccessful if wrong key size.
|
||||||
|
*/
|
||||||
|
bool bytes_to_words(const char *src, size_t len, std::string& words,
|
||||||
|
const std::string &language_name);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Converts bytes (secret key) to seed words.
|
* \brief Converts bytes (secret key) to seed words.
|
||||||
* \param src Secret key
|
* \param src Secret key
|
||||||
|
|
Loading…
Reference in New Issue