Electroneum
crypto::ElectrumWords Namespace Reference

Mnemonic seed word generation and wallet restoration helper functions. More...

Functions

std::vector< const Language::Base * > get_language_list ()
 
bool words_to_bytes (const epee::wipeable_string &words, epee::wipeable_string &dst, size_t len, bool duplicate, std::string &language_name)
 Converts seed words to bytes (secret key). More...
 
bool words_to_bytes (const epee::wipeable_string &words, crypto::secret_key &dst, std::string &language_name)
 Converts seed words to bytes (secret key). More...
 
bool bytes_to_words (const char *src, size_t len, epee::wipeable_string &words, const std::string &language_name)
 Converts bytes (secret key) to seed words. More...
 
bool bytes_to_words (const crypto::secret_key &src, epee::wipeable_string &words, const std::string &language_name)
 Converts bytes (secret key) to seed words. More...
 
void get_language_list (std::vector< std::string > &languages, bool english)
 Gets a list of seed languages that are supported. More...
 
bool get_is_old_style_seed (const epee::wipeable_string &seed)
 Tells if the seed passed is an old style seed or not. More...
 
std::string get_english_name_for (const std::string &name)
 Returns the name of a language in English. More...
 

Variables

const int seed_length = 24
 
const std::string old_language_name = "EnglishOld"
 

Detailed Description

Mnemonic seed word generation and wallet restoration helper functions.

Function Documentation

◆ bytes_to_words() [1/2]

bool crypto::ElectrumWords::bytes_to_words ( const char *  src,
size_t  len,
epee::wipeable_string words,
const std::string &  language_name 
)

Converts bytes (secret key) to seed words.

Converts bytes to seed words.

Parameters
srcSecret key
wordsSpace delimited concatenated words get written here.
language_nameSeed language name
Returns
true if successful false if not. Unsuccessful if wrong key size.
Parameters
srcSecret data
lenSecret data length in bytes (positive multiples of 4 only)
wordsSpace delimited concatenated words get written here.
language_nameSeed language name
Returns
true if successful false if not. Unsuccessful if wrong key size.

Definition at line 383 of file electrum-words.cpp.

385  {
386 
387  if (len % 4 != 0 || len == 0) return false;
388 
389  const Language::Base *language = NULL;
390  const std::vector<const Language::Base*> language_list = crypto::ElectrumWords::get_language_list();
391  for (const Language::Base *l: language_list)
392  {
393  if (language_name == l->get_language_name() || language_name == l->get_english_language_name())
394  language = l;
395  }
396  if (!language)
397  {
398  return false;
399  }
400  const std::vector<std::string> &word_list = language->get_word_list();
401  // To store the words for random access to add the checksum word later.
402  std::vector<epee::wipeable_string> words_store;
403 
404  uint32_t word_list_length = word_list.size();
405  // 4 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
406  for (unsigned int i=0; i < len/4; i++, words.push_back(' '))
407  {
408  uint32_t w[4];
409 
410  w[0] = SWAP32LE(*(const uint32_t*)(src + (i * 4)));
411 
412  w[1] = w[0] % word_list_length;
413  w[2] = ((w[0] / word_list_length) + w[1]) % word_list_length;
414  w[3] = (((w[0] / word_list_length) / word_list_length) + w[2]) % word_list_length;
415 
416  words += word_list[w[1]];
417  words += ' ';
418  words += word_list[w[2]];
419  words += ' ';
420  words += word_list[w[3]];
421 
422  words_store.push_back(word_list[w[1]]);
423  words_store.push_back(word_list[w[2]]);
424  words_store.push_back(word_list[w[3]]);
425 
426  memwipe(w, sizeof(w));
427  }
428 
429  words += words_store[create_checksum_index(words_store, language)];
430  return true;
431  }
const std::vector< std::string > & get_word_list() const
Returns a pointer to the word list.
std::vector< const Language::Base * > get_language_list()
A base language class which all languages have to inherit from for Polymorphism.
unsigned int uint32_t
Definition: stdint.h:126
void * memwipe(void *src, size_t n)
#define SWAP32LE
Definition: int-util.h:244
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bytes_to_words() [2/2]

bool crypto::ElectrumWords::bytes_to_words ( const crypto::secret_key src,
epee::wipeable_string words,
const std::string &  language_name 
)

Converts bytes (secret key) to seed words.

Parameters
srcSecret key
wordsSpace delimited concatenated words get written here.
language_nameSeed language name
Returns
true if successful false if not. Unsuccessful if wrong key size.

Definition at line 433 of file electrum-words.cpp.

435  {
436  return bytes_to_words(src.data, sizeof(src), words, language_name);
437  }
bool bytes_to_words(const crypto::secret_key &src, epee::wipeable_string &words, const std::string &language_name)
Converts bytes (secret key) to seed words.
Here is the call graph for this function:

◆ get_english_name_for()

std::string crypto::ElectrumWords::get_english_name_for ( const std::string &  name)

Returns the name of a language in English.

Parameters
namethe name of the language in its own language
Returns
the name of the language in English

Definition at line 484 of file electrum-words.cpp.

485  {
486  const std::vector<const Language::Base*> language_instances = get_language_list();
487  for (std::vector<const Language::Base*>::const_iterator it = language_instances.begin();
488  it != language_instances.end(); it++)
489  {
490  if ((*it)->get_language_name() == name)
491  return (*it)->get_english_language_name();
492  }
493  return "<language not found>";
494  }
void get_language_list(std::vector< std::string > &languages, bool english)
Gets a list of seed languages that are supported.
const char * name
Here is the call graph for this function:

◆ get_is_old_style_seed()

bool crypto::ElectrumWords::get_is_old_style_seed ( const epee::wipeable_string seed)

Tells if the seed passed is an old style seed or not.

Parameters
seedThe seed to check (a space delimited concatenated word list)
Returns
true if the seed passed is a old style seed false if not.

Definition at line 477 of file electrum-words.cpp.

478  {
479  std::vector<epee::wipeable_string> word_list;
480  seed.split(word_list);
481  return word_list.size() != (seed_length + 1);
482  }
void split(std::vector< wipeable_string > &fields) const
Here is the call graph for this function:

◆ get_language_list() [1/2]

std::vector< const Language::Base * > crypto::ElectrumWords::get_language_list ( )

◆ get_language_list() [2/2]

void crypto::ElectrumWords::get_language_list ( std::vector< std::string > &  languages,
bool  english 
)

Gets a list of seed languages that are supported.

Parameters
languagesThe vector is set to the list of languages.
languagesA vector is set to the list of languages.
englishwhether to get the names in English or the language language

Definition at line 462 of file electrum-words.cpp.

463  {
464  const std::vector<const Language::Base*> language_instances = get_language_list();
465  for (std::vector<const Language::Base*>::const_iterator it = language_instances.begin();
466  it != language_instances.end(); it++)
467  {
468  languages.push_back(english ? (*it)->get_english_language_name() : (*it)->get_language_name());
469  }
470  }
void get_language_list(std::vector< std::string > &languages, bool english)
Gets a list of seed languages that are supported.
Here is the call graph for this function:

◆ words_to_bytes() [1/2]

bool crypto::ElectrumWords::words_to_bytes ( const epee::wipeable_string words,
epee::wipeable_string dst,
size_t  len,
bool  duplicate,
std::string &  language_name 
)

Converts seed words to bytes (secret key).

Parameters
wordsString containing the words separated by spaces.
dstTo put the secret data restored from the words.
lenThe number of bytes to expect, 0 if unknown
duplicateIf true and len is not zero, we accept half the data, and duplicate it
language_nameLanguage of the seed as found gets written here.
Returns
false if not a multiple of 3 words, or if word is not in the words list

Definition at line 266 of file electrum-words.cpp.

268  {
269  std::vector<epee::wipeable_string> seed;
270 
271  words.split(seed);
272 
273  if (len % 4)
274  {
275  MERROR("Invalid seed: not a multiple of 4");
276  return false;
277  }
278 
279  bool has_checksum = true;
280  if (len)
281  {
282  // error on non-compliant word list
283  const size_t expected = len * 8 * 3 / 32;
284  if (seed.size() != expected/2 && seed.size() != expected &&
285  seed.size() != expected + 1)
286  {
287  MERROR("Invalid seed: unexpected number of words");
288  return false;
289  }
290 
291  // If it is seed with a checksum.
292  has_checksum = seed.size() == (expected + 1);
293  }
294 
295  std::vector<uint32_t> matched_indices;
296  auto wiper = epee::misc_utils::create_scope_leave_handler([&](){memwipe(matched_indices.data(), matched_indices.size() * sizeof(matched_indices[0]));});
297  Language::Base *language;
298  if (!find_seed_language(seed, has_checksum, matched_indices, &language))
299  {
300  MERROR("Invalid seed: language not found");
301  return false;
302  }
303  language_name = language->get_language_name();
304  uint32_t word_list_length = language->get_word_list().size();
305 
306  if (has_checksum)
307  {
308  if (!checksum_test(seed, language))
309  {
310  // Checksum fail
311  MERROR("Invalid seed: invalid checksum");
312  return false;
313  }
314  seed.pop_back();
315  }
316 
317  for (unsigned int i=0; i < seed.size() / 3; i++)
318  {
319  uint32_t w[4];
320  w[1] = matched_indices[i*3];
321  w[2] = matched_indices[i*3 + 1];
322  w[3] = matched_indices[i*3 + 2];
323 
324  w[0]= w[1] + word_list_length * (((word_list_length - w[1]) + w[2]) % word_list_length) +
325  word_list_length * word_list_length * (((word_list_length - w[2]) + w[3]) % word_list_length);
326 
327  if (!(w[0]% word_list_length == w[1]))
328  {
329  memwipe(w, sizeof(w));
330  MERROR("Invalid seed: mumble mumble");
331  return false;
332  }
333 
334  w[0] = SWAP32LE(w[0]);
335  dst.append((const char*)&w[0], 4); // copy 4 bytes to position
336  memwipe(w, sizeof(w));
337  }
338 
339  if (len > 0 && duplicate)
340  {
341  const size_t expected = len * 3 / 32;
342  if (seed.size() == expected/2)
343  {
344  dst.append(dst.data(), dst.size()); // if electrum 12-word seed, duplicate
345  }
346  }
347 
348  return true;
349  }
#define MERROR(x)
Definition: misc_log_ex.h:73
size_t size() const noexcept
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
A base language class which all languages have to inherit from for Polymorphism.
void append(const char *ptr, size_t len)
void split(std::vector< wipeable_string > &fields) const
unsigned int uint32_t
Definition: stdint.h:126
void * memwipe(void *src, size_t n)
const char * data() const noexcept
#define SWAP32LE
Definition: int-util.h:244
Here is the call graph for this function:
Here is the caller graph for this function:

◆ words_to_bytes() [2/2]

bool crypto::ElectrumWords::words_to_bytes ( const epee::wipeable_string words,
crypto::secret_key dst,
std::string &  language_name 
)

Converts seed words to bytes (secret key).

Parameters
wordsString containing the words separated by spaces.
dstTo put the secret key restored from the words.
language_nameLanguage of the seed as found gets written here.
Returns
false if not a multiple of 3 words, or if word is not in the words list

Definition at line 358 of file electrum-words.cpp.

360  {
362  if (!words_to_bytes(words, s, sizeof(dst), true, language_name))
363  {
364  MERROR("Invalid seed: failed to convert words to bytes");
365  return false;
366  }
367  if (s.size() != sizeof(dst))
368  {
369  MERROR("Invalid seed: wrong output size");
370  return false;
371  }
372  dst = *(const crypto::secret_key*)s.data();
373  return true;
374  }
#define MERROR(x)
Definition: misc_log_ex.h:73
size_t size() const noexcept
const char * data() const noexcept
bool words_to_bytes(const epee::wipeable_string &words, crypto::secret_key &dst, std::string &language_name)
Converts seed words to bytes (secret key).
Here is the call graph for this function:

Variable Documentation

◆ old_language_name

const std::string crypto::ElectrumWords::old_language_name = "EnglishOld"

Definition at line 65 of file electrum-words.h.

◆ seed_length

const int crypto::ElectrumWords::seed_length = 24

Definition at line 64 of file electrum-words.h.