1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use clap::Parser;
use std::path::PathBuf;
/// This enum, `ListChoice`, represents all of the "built-in" word lists that Phraze can use.
#[derive(Clone, Debug, Copy)]
pub enum ListChoice {
Long,
Medium,
Eff,
Mnemonicode,
Effshort,
Qwerty,
Alpha,
}
/// Generate random passphrases
#[derive(Parser, Debug)]
#[clap(version, name = "phraze")]
pub struct Args {
/// Strengthen your passphrase the easy way: Each -S flag increases minimum entropy by 20 bits (above the default of
/// 80 bits).
#[clap(short = 'S', long = "strength", conflicts_with = "number_of_words", conflicts_with = "minimum_entropy", action = clap::ArgAction::Count)]
pub strength_count: u8,
/// Set minimum amount of entropy in bits for generated passphrase. If neither minimum_entropy or
/// number_of_words is specified, Phraze will default to an 80-bit minimum.
#[clap(
short = 'e',
long = "minimum-entropy",
conflicts_with = "number_of_words",
conflicts_with = "strength_count"
)]
pub minimum_entropy: Option<usize>,
/// Set exactly how many words to use in generated passphrase. If neither number_of_words or
/// minimum_entropy is specified, Phraze will default to an 80-bit minimum.
#[clap(
short = 'w',
long = "words",
conflicts_with = "minimum_entropy",
conflicts_with = "strength_count"
)]
pub number_of_words: Option<usize>,
/// Number of passphrases to generate
#[clap(short = 'n', long = "passphrases", default_value = "1")]
pub n_passphrases: usize,
/// Word separator. Can accept single quotes around the separator. To not use a separator,
/// use empty single quotes: ''.
///
/// There are special values that will trigger generated separators:
///
/// _n: separators will be random numbers
///
/// _s: separators will be random symbols
///
/// _b: separators will be a mix of random numbers and symbols
#[clap(short = 's', long = "sep", default_value = "-")]
pub separator: String,
/// Choose a word list to use.
///
/// Options:
///
/// m: Orchard Street Medium List (8,192 words) [DEFAULT]
///
/// l: Orchard Street Long List (17,576 words)
///
/// e: EFF Long List (7,776 words)
///
/// n: Mnemonicode list (1,633 words). Good if you know you're going to be speaking
/// passphrases out loud.
///
/// s: EFF Short List (1,296 words)
///
/// q: Orchard Street QWERTY List (1,296 words). Optimized to minimize travel
/// distance on QWERTY keyboard layout.
///
/// a: Orchard Street Alpha List (1,296 words). Optimized to minimize travel
/// distance on alphabetical keyboard layout.
#[clap(short = 'l', long = "list", value_parser=parse_list_choice, default_value="m")]
pub list_choice: ListChoice,
/// Provide a text file with a list of words to randomly generate passphrase
/// from. Should be a text file with one word per line.
#[clap(short = 'c', long = "custom-list", conflicts_with = "list_choice")]
pub custom_list_file_path: Option<PathBuf>,
/// Use Title Case for words in generated passphrase
#[clap(short = 't', long = "title-case")]
pub title_case: bool,
/// Print estimated entropy of generated passphrase, in bits, along with
/// the passphrase itself
#[clap(short = 'v', long = "verbose")]
pub verbose: bool,
}
/// Convert list_choice string slice into a ListChoice enum. Clap calls this function.
fn parse_list_choice(list_choice: &str) -> Result<ListChoice, String> {
match list_choice.to_lowercase().as_ref() {
"l" => Ok(ListChoice::Long),
"m" => Ok(ListChoice::Medium),
"e" => Ok(ListChoice::Eff),
"n" => Ok(ListChoice::Mnemonicode),
"s" => Ok(ListChoice::Effshort),
"q" => Ok(ListChoice::Qwerty),
"a" => Ok(ListChoice::Alpha),
_ => Err(format!(
"Inputted list choice '{}' doesn't correspond to an available word list",
list_choice
)),
}
}