diff options
author | Jesse Luehrs <doy@tozt.net> | 2020-04-11 16:03:30 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2020-04-11 16:03:30 -0400 |
commit | 85e3c46466119c94724a7b48d22eda7e50538505 (patch) | |
tree | 4f18fd77b1ce19eec70023d075ea36136b3c2c9a /src | |
parent | 40a3cf1ee2124419c3c9336b5849652e74d4a00b (diff) | |
download | rbw-85e3c46466119c94724a7b48d22eda7e50538505.tar.gz rbw-85e3c46466119c94724a7b48d22eda7e50538505.zip |
add password generation
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/rbw.rs | 57 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/pwgen.rs | 64 |
3 files changed, 117 insertions, 5 deletions
diff --git a/src/bin/rbw.rs b/src/bin/rbw.rs index 9a968ff..0671080 100644 --- a/src/bin/rbw.rs +++ b/src/bin/rbw.rs @@ -159,10 +159,19 @@ fn add() { todo!() } -fn generate() { - ensure_agent(); +fn generate( + name: Option<&str>, + user: Option<&str>, + len: usize, + ty: rbw::pwgen::Type, +) { + let pw = rbw::pwgen::pwgen(ty, len); + println!("{}", std::str::from_utf8(pw.data()).unwrap()); - todo!() + if name.is_some() && user.is_some() { + ensure_agent(); + todo!(); + } } fn edit() { @@ -230,7 +239,27 @@ fn main() { .arg(clap::Arg::with_name("user")), ) .subcommand(clap::SubCommand::with_name("add")) - .subcommand(clap::SubCommand::with_name("generate")) + .subcommand( + clap::SubCommand::with_name("generate") + .arg(clap::Arg::with_name("len").required(true)) + .arg(clap::Arg::with_name("name")) + .arg(clap::Arg::with_name("user")) + .arg(clap::Arg::with_name("no-symbols").long("no-symbols")) + .arg( + clap::Arg::with_name("only-numbers").long("only-numbers"), + ) + .arg( + clap::Arg::with_name("nonconfusables") + .long("nonconfusables"), + ) + .arg(clap::Arg::with_name("diceware").long("diceware")) + .group(clap::ArgGroup::with_name("password-type").args(&[ + "no-symbols", + "only-numbers", + "nonconfusables", + "diceware", + ])), + ) .subcommand(clap::SubCommand::with_name("edit")) .subcommand(clap::SubCommand::with_name("remove")) .subcommand(clap::SubCommand::with_name("lock")) @@ -259,7 +288,25 @@ fn main() { smatches.value_of("user"), ), ("add", Some(_)) => add(), - ("generate", Some(_)) => generate(), + ("generate", Some(smatches)) => { + let ty = if smatches.is_present("no-symbols") { + rbw::pwgen::Type::NoSymbols + } else if smatches.is_present("only-numbers") { + rbw::pwgen::Type::Numbers + } else if smatches.is_present("nonconfusables") { + rbw::pwgen::Type::NonConfusables + } else if smatches.is_present("diceware") { + rbw::pwgen::Type::Diceware + } else { + rbw::pwgen::Type::AllChars + }; + generate( + smatches.value_of("name"), + smatches.value_of("user"), + smatches.value_of("len").unwrap().parse().unwrap(), + ty, + ); + } ("edit", Some(_)) => edit(), ("remove", Some(_)) => remove(), ("lock", Some(_)) => lock(), @@ -17,3 +17,4 @@ pub mod identity; pub mod locked; pub mod pinentry; mod prelude; +pub mod pwgen; diff --git a/src/pwgen.rs b/src/pwgen.rs new file mode 100644 index 0000000..656305e --- /dev/null +++ b/src/pwgen.rs @@ -0,0 +1,64 @@ +use chbs::scheme::ToScheme as _; +use rand::seq::SliceRandom as _; +use zeroize::Zeroize as _; + +const SYMBOLS: &[u8] = b"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; +const NUMBERS: &[u8] = b"0123456789"; +const LETTERS: &[u8] = + b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +const NONCONFUSABLES: &[u8] = b"34678abcdefhjkmnpqrtuwxy"; + +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub enum Type { + AllChars, + NoSymbols, + Numbers, + NonConfusables, + Diceware, +} + +pub fn pwgen(ty: Type, len: usize) -> crate::locked::Vec { + if ty == Type::Diceware { + let mut locked_pass = crate::locked::Vec::new(); + let mut config = chbs::config::BasicConfig::default(); + config.words = len; + config.capitalize_first = chbs::probability::Probability::Never; + config.capitalize_words = chbs::probability::Probability::Never; + let mut pass = config.to_scheme().generate(); + locked_pass.extend(pass.as_bytes().iter().copied()); + pass.zeroize(); + return locked_pass; + } + + let alphabet = match ty { + Type::AllChars => { + let mut v = vec![]; + v.extend(SYMBOLS.iter().copied()); + v.extend(NUMBERS.iter().copied()); + v.extend(LETTERS.iter().copied()); + v + } + Type::NoSymbols => { + let mut v = vec![]; + v.extend(NUMBERS.iter().copied()); + v.extend(LETTERS.iter().copied()); + v + } + Type::Numbers => { + let mut v = vec![]; + v.extend(NUMBERS.iter().copied()); + v + } + Type::NonConfusables => { + let mut v = vec![]; + v.extend(NONCONFUSABLES.iter().copied()); + v + } + Type::Diceware => unreachable!(), + }; + + let mut rng = rand::thread_rng(); + let mut pass = crate::locked::Vec::new(); + pass.extend(alphabet.choose_multiple(&mut rng, len).copied()); + pass +} |