1use rand::prelude::IteratorRandom;
2
3const WORDLIST: &str = include_str!("../eff_large.wordlist");
4
5const PRINTABLE_ASCII: &str = r#"!"$#%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"#;
6
7pub fn generate_passphrase(len: u8, separator: &str) -> String {
8 let phrase_iterable = (0..len).map(|_| random_word());
9 itertools::intersperse(phrase_iterable, separator).collect()
10}
11
12pub fn generate_password(len: u8) -> String {
13 (0..len).map(|_| random_ascii()).collect()
14}
15
16fn random_word() -> &'static str {
17 WORDLIST.lines().choose(&mut rand::rng()).unwrap()
18}
19
20pub fn random_ascii() -> char {
21 PRINTABLE_ASCII.chars().choose(&mut rand::rng()).unwrap()
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use itertools::Itertools;
28
29 #[test]
30 fn test_wordlist() {
31 let unique: Vec<_> = WORDLIST.lines().unique().collect();
32 let len = unique.len();
33 assert!(
34 len > 5000,
35 "wordlist should have > 5000 unique entries; has only {}",
36 len
37 );
38 }
39}