switch to diceware platform independent word list (EffLong)

This commit is contained in:
2026-04-25 07:31:22 -04:00
parent 383a1a2b8b
commit 3734306830
3 changed files with 27 additions and 12 deletions
Generated
+7
View File
@@ -29,6 +29,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "diceware_wordlists"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f9b52b69d268c7a2bc582e3aec5cdfa43ac91cef4fe6b6751b02da2b43d6166"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.17" version = "0.2.17"
@@ -89,6 +95,7 @@ name = "password-generator"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"diceware_wordlists",
"rand", "rand",
"webster", "webster",
] ]
+1
View File
@@ -7,3 +7,4 @@ edition = "2024"
rand = "0.8" rand = "0.8"
webster = "0.3.0" webster = "0.3.0"
bitflags = "2" bitflags = "2"
diceware_wordlists = "1.2.3"
+19 -12
View File
@@ -3,10 +3,12 @@ use rand::rngs::OsRng;
use rand::SeedableRng; use rand::SeedableRng;
use rand::rngs::StdRng; use rand::rngs::StdRng;
use std::fs; // use std::fs;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use bitflags::bitflags; use bitflags::bitflags;
use diceware_wordlists::Wordlist;
const UPPERCASE_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const UPPERCASE_CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const LOWERCASE_CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz"; const LOWERCASE_CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
const NUMBER_CHARS: &[u8] = b"0123456789"; const NUMBER_CHARS: &[u8] = b"0123456789";
@@ -196,14 +198,13 @@ fn generate_password(config: &PasswordConfig, rng: &mut impl Rng) -> Result<Stri
Ok(res) Ok(res)
} }
// todo: haven't updated bits of entropy since adding capitalization, symbols and numbers // todo: haven't updated bits of entropy comments since adding capitalization,
// it will add a few, but not many since it's fairly predictable // symbols, numbers and changing to diceware wordlist
// //
// How many bits of entropy? // How many bits of entropy?
// log2(104078) -> 16.6 bits per word derived from word_list size // log2(104078) -> 16.6 bits per word derived from word_list size
// log2(18) -> 4.1 bits for separator assuming seporator is one of our SYMBOLs // log2(18) -> 4.1 bits for separator assuming seporator is one of our SYMBOLs
// total 70.5 bits of entropy // total 70.5 bits of entropy
// note: dictionary is provided by linux, so entropy is platform dependent ATM
// //
// we can take a slice of "words" because we don't care about: // we can take a slice of "words" because we don't care about:
// capacity, mutation (push/pop), allocation strategy // capacity, mutation (push/pop), allocation strategy
@@ -240,16 +241,22 @@ fn random_word<'a>(word_list: &[&'a str], rng: &mut impl Rng) -> &'a str {
word_list[rng.gen_range(0..word_list.len())] word_list[rng.gen_range(0..word_list.len())]
} }
fn main() { fn get_word_list() -> &'static [&'static str] {
// todo: not cross-platform // platform dependent word list
// todo: abstract this a bit // let content = fs::read_to_string("/usr/share/dict/words")
let content = fs::read_to_string("/usr/share/dict/words") // .expect("could not read dictionary");
.expect("could not read dictionary");
// filter words here for only ascii // filter words here for only ascii
// word_list length is 104078 // word_list length is 104078
let word_list: Vec<&str> = content.lines().filter(|w| // let word_list: Vec<&str> = content.lines().filter(|w|
w.is_ascii()).collect(); // w.is_ascii()).collect();
// platform independent word list
// this list doesn't seem to contain non-ascii or even punctuation
Wordlist::get_list(&Wordlist::EffLong)
}
fn main() {
let word_list = get_word_list();
// we definitely want to use the OS for randomness // we definitely want to use the OS for randomness
// doesn't require seeding because it is backed by CSPRNG, backed by OS // doesn't require seeding because it is backed by CSPRNG, backed by OS