From 85e3c46466119c94724a7b48d22eda7e50538505 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 11 Apr 2020 16:03:30 -0400 Subject: add password generation --- Cargo.lock | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 + src/bin/rbw.rs | 57 ++++++++++++++++++++-- src/lib.rs | 1 + src/pwgen.rs | 64 +++++++++++++++++++++++++ 5 files changed, 267 insertions(+), 6 deletions(-) create mode 100644 src/pwgen.rs diff --git a/Cargo.lock b/Cargo.lock index 2ffed19..c157b72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,6 +91,28 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +[[package]] +name = "backtrace" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" +dependencies = [ + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "base64" version = "0.9.3" @@ -206,6 +228,17 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "chbs" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b8579452901e185b65f91bc5571f9543ede86f3238389105a0f44dd4b9a82ab" +dependencies = [ + "derive_builder", + "failure", + "rand 0.7.3", +] + [[package]] name = "clap" version = "2.33.0" @@ -215,7 +248,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -283,6 +316,66 @@ dependencies = [ "libc", ] +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.9.3", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" +dependencies = [ + "darling", + "derive_builder_core", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.8.1" @@ -348,6 +441,28 @@ dependencies = [ "termcolor", ] +[[package]] +name = "failure" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -585,6 +700,12 @@ dependencies = [ "tokio-tls", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.0" @@ -1019,6 +1140,7 @@ dependencies = [ "arrayvec", "base64 0.11.0", "block-modes", + "chbs", "clap", "daemonize", "directories", @@ -1028,6 +1150,7 @@ dependencies = [ "log", "nix", "pbkdf2", + "rand 0.7.3", "region", "reqwest", "serde", @@ -1143,6 +1266,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" + [[package]] name = "ryu" version = "1.0.3" @@ -1304,6 +1433,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "subtle" version = "1.0.0" @@ -1321,6 +1456,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8bd73cd..526d8f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "*" arrayvec = "*" base64 = "*" block-modes = "*" +chbs = "*" clap = "*" daemonize = "*" directories = "*" @@ -19,6 +20,7 @@ hmac = "*" log = "*" nix = "*" pbkdf2 = "*" +rand = "*" region = "*" reqwest = { version = "*", features = ["blocking", "json"] } serde = { version = "*", features = ["derive"] } 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(), diff --git a/src/lib.rs b/src/lib.rs index d197fbb..e5d887a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 +} -- cgit v1.2.3-54-g00ecf