From 60144920f3e24ea96c1907889eee9c5843a3a206 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Wed, 10 Nov 2021 08:52:58 +1100 Subject: [PATCH 1/2] Allow word count multiples of 3 instead of 6 BIP39 says > The allowed size of ENT is 128-256 bits. Once we add the checksum this is 132-264 bits. This is divided by 11 to get the word count. From the BIP141 ``` CS = ENT / 32 MS = (ENT + CS) / 11 | ENT | CS | ENT+CS | MS | +-------+----+--------+------+ | 128 | 4 | 132 | 12 | | 160 | 5 | 165 | 15 | | 192 | 6 | 198 | 18 | | 224 | 7 | 231 | 21 | | 256 | 8 | 264 | 24 | ``` Currently we are limiting word count to be a multiple of 6, I do not know why this is being done but from reading the BIP it seems that 15 is a valid word count value. Allow word count of 15 by checking the word count modulo 3 instead of modulo 6. Since this check appears twice in the code, add a helper function to reduce code duplication. Fixes: #15 --- src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 79cb52f..1df56fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -250,7 +250,7 @@ impl Mnemonic { where R: rand_core::RngCore + rand_core::CryptoRng, { - if word_count < MIN_NB_WORDS || word_count % 6 != 0 || word_count > MAX_NB_WORDS { + if is_invalid_word_count(word_count) { return Err(Error::BadWordCount(word_count)); } @@ -377,7 +377,7 @@ impl Mnemonic { /// Parse a mnemonic in normalized UTF8 in the given language. pub fn parse_in_normalized(language: Language, s: &str) -> Result { let nb_words = s.split_whitespace().count(); - if nb_words < MIN_NB_WORDS || nb_words % 6 != 0 || nb_words > MAX_NB_WORDS { + if is_invalid_word_count(nb_words) { return Err(Error::BadWordCount(nb_words)); } @@ -558,6 +558,10 @@ impl str::FromStr for Mnemonic { } } +fn is_invalid_word_count(word_count: usize) -> bool { + word_count < MIN_NB_WORDS || word_count % 3 != 0 || word_count > MAX_NB_WORDS +} + #[cfg(test)] mod tests { use super::*; From af958a253a62739e7fb1976bc7282b8c832408b5 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Wed, 10 Nov 2021 08:57:52 +1100 Subject: [PATCH 2/2] Add unit test for valid word counts We just enabled word counts of 15, add a unit test that verifies all the valid word count values. --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 1df56fa..05963e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -609,6 +609,14 @@ mod tests { let _ = Mnemonic::generate_in_with(&mut rand::thread_rng(), Language::English, 24).unwrap(); } + #[cfg(feature = "rand")] + #[test] + fn test_generate_word_counts() { + for word_count in [12, 15, 18, 21, 24].iter() { + let _ = Mnemonic::generate(*word_count).unwrap(); + } + } + #[test] fn test_vectors_english() { // These vectors are tuples of