Skip to content

Commit

Permalink
feat: language detection for mnemonic seed words
Browse files Browse the repository at this point in the history
Implementation of a basic language detection algorithm for mnemonic words

Review comments

cleanup
  • Loading branch information
StriderDM committed Nov 19, 2021
1 parent 337bc6f commit 148e5e7
Showing 1 changed file with 44 additions and 10 deletions.
54 changes: 44 additions & 10 deletions base_layer/key_manager/src/mnemonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use tari_crypto::tari_utilities::bit::*;
/// It can autodetect the language of the Mnemonic word sequence
// TODO: Develop a language autodetection mechanism to distinguish between ChineseTraditional and ChineseSimplified

#[derive(Clone, Debug, PartialEq, EnumString, Display)]
#[derive(Clone, Debug, PartialEq, EnumString, Display, Copy)]
pub enum MnemonicLanguage {
ChineseSimplified,
English,
Expand All @@ -47,12 +47,8 @@ pub enum MnemonicLanguage {
impl MnemonicLanguage {
/// Detects the mnemonic language of a specific word by searching all defined mnemonic word lists
pub fn from(mnemonic_word: &str) -> Result<MnemonicLanguage, MnemonicError> {
for language in MnemonicLanguage::iterator() {
if find_mnemonic_index_from_word(mnemonic_word, language).is_ok() {
return Ok((*language).clone());
}
}
Err(MnemonicError::UnknownLanguage)
let words = vec![mnemonic_word.to_string()];
detect_language(&words)
}

/// Returns an iterator for the MnemonicLanguage enum group to allow iteration over all defined languages
Expand Down Expand Up @@ -158,11 +154,49 @@ pub fn from_bytes(bytes: Vec<u8>, language: &MnemonicLanguage) -> Result<Vec<Str
Ok(mnemonic_sequence)
}

fn detect_language(words: &[String]) -> Result<MnemonicLanguage, MnemonicError> {
if words.iter().len() < 1 {
return Err(MnemonicError::UnknownLanguage);
}

let mut index: usize = 0;
let count = words.iter().len() - 1;

while index <= count {
let mut languages = Vec::new();
let word = words.get(index).ok_or(MnemonicError::EncodeInvalidLength)?;
for language in MnemonicLanguage::iterator() {
if find_mnemonic_index_from_word(word, language).is_ok() {
languages.push(*language);
}
}

for language in languages {
let mut consistent = true;
for i in 0..count {
// exclude initial word
if i != index {
let compare = words.get(i).ok_or(MnemonicError::EncodeInvalidLength)?;
if find_mnemonic_index_from_word(compare, &language).is_err() {
consistent = false;
}
}
}
if consistent {
return Ok(language);
}
}

index += 1;
}

Err(MnemonicError::UnknownLanguage)
}

/// Generates a vector of bytes that represent the provided mnemonic sequence of words, the language of the mnemonic
/// sequence is autodetected
/// sequence is detected
pub fn to_bytes(mnemonic_seq: &[String]) -> Result<Vec<u8>, MnemonicError> {
let first_word = mnemonic_seq.get(0).ok_or(MnemonicError::EncodeInvalidLength)?;
let language = MnemonicLanguage::from(first_word)?; // Autodetect language
let language = self::detect_language(mnemonic_seq)?;
to_bytes_with_language(mnemonic_seq, &language)
}

Expand Down

0 comments on commit 148e5e7

Please sign in to comment.