aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock149
-rw-r--r--Cargo.toml2
-rw-r--r--src/bin/rbw.rs57
-rw-r--r--src/lib.rs1
-rw-r--r--src/pwgen.rs64
5 files changed, 267 insertions, 6 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2ffed19..c157b72 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -92,6 +92,28 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -207,6 +229,17 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -215,7 +248,7 @@ dependencies = [
"ansi_term",
"atty",
"bitflags",
- "strsim",
+ "strsim 0.8.0",
"textwrap",
"unicode-width",
"vec_map",
@@ -284,6 +317,66 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -349,6 +442,28 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -586,6 +701,12 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -1144,6 +1267,12 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1305,6 +1434,12 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1322,6 +1457,18 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
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
+}