Electroneum
Loading...
Searching...
No Matches
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).
bool words_to_bytes (const epee::wipeable_string &words, crypto::secret_key &dst, std::string &language_name)
 Converts seed words to bytes (secret key).
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.
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.
void get_language_list (std::vector< std::string > &languages, bool english)
 Gets a list of seed languages that are supported.
bool get_is_old_style_seed (const epee::wipeable_string &seed)
 Tells if the seed passed is an old style seed or not.
std::string get_english_name_for (const std::string &name)
 Returns the name of a language in English.

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 }
A base language class which all languages have to inherit from for Polymorphism.
const std::vector< std::string > & get_word_list() const
Returns a pointer to the word list.
#define SWAP32LE
Definition int-util.h:224
void * memwipe(void *src, size_t n)
std::vector< const Language::Base * > get_language_list()
unsigned int uint32_t
Definition stdint.h:126
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 char *src, size_t len, 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 }
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]

◆ 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 }
Here is the call graph for this function:

◆ words_to_bytes() [1/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 }
const char * data() const noexcept
size_t size() const noexcept
#define MERROR(x)
Definition misc_log_ex.h:73
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).
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
Here is the call graph for this function:

◆ words_to_bytes() [2/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 }
void append(const char *ptr, size_t len)
unsigned int uint32_t
Definition hash.h:127
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
Here is the call graph for this function:
Here is the caller 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.