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
This commit is contained in:
Tobin Harding 2021-11-10 08:52:58 +11:00
parent 520e15a6e5
commit 60144920f3
1 changed files with 6 additions and 2 deletions

View File

@ -250,7 +250,7 @@ impl Mnemonic {
where where
R: rand_core::RngCore + rand_core::CryptoRng, 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)); return Err(Error::BadWordCount(word_count));
} }
@ -377,7 +377,7 @@ impl Mnemonic {
/// Parse a mnemonic in normalized UTF8 in the given language. /// Parse a mnemonic in normalized UTF8 in the given language.
pub fn parse_in_normalized(language: Language, s: &str) -> Result<Mnemonic, Error> { pub fn parse_in_normalized(language: Language, s: &str) -> Result<Mnemonic, Error> {
let nb_words = s.split_whitespace().count(); 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)); 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;