From 9cf0759b7a2047b5bd15a453a009a4513dfbcebd Mon Sep 17 00:00:00 2001 From: Michael Pfaff Date: Tue, 19 Dec 2023 20:21:18 -0500 Subject: [PATCH] Initial commit --- .gitignore | 1 + Cargo.lock | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 11 +++ LICENSE.md | 24 ++++++ rules.toml | 19 +++++ src/main.rs | 84 ++++++++++++++++++++ 6 files changed, 359 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE.md create mode 100644 rules.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..007d729 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,220 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "password-gen" +version = "0.1.0" +dependencies = [ + "rand", + "serde", + "toml", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +dependencies = [ + "serde", +] + +[[package]] +name = "syn" +version = "2.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +dependencies = [ + "memchr", +] + +[[patch.unused]] +name = "brisk" +version = "0.1.0" + +[[patch.unused]] +name = "how" +version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..da444d8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "password-gen" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" +serde = { version = "1.0.193", features = ["derive"] } +toml = { version = "0.8.8", default-features = false, features = ["parse"] } diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/rules.toml b/rules.toml new file mode 100644 index 0000000..68a73d9 --- /dev/null +++ b/rules.toml @@ -0,0 +1,19 @@ +[password] +length = 24 +lowercase = true +uppercase = true +numbers = true + +[passphrase] +count = 6 +delimiters = [' '] +# download from https://raw.githubusercontent.com/dwyl/english-words/master/words_alpha.txt +words = "words.txt" + +[mycarletonone] +length = 15 +lowercase = true +uppercase = true +numbers = true +special_characters = ['!', '.', '_'] + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c434870 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,84 @@ +#![feature(iter_intersperse)] + +#[macro_use] +extern crate serde; + +use std::collections::{HashMap, HashSet}; + +use rand::Rng; +use rand::distributions::Slice as SliceDist; + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +enum RuleSet { + Password { + length: usize, + lowercase: bool, + uppercase: bool, + numbers: bool, + #[serde(default = "default_special_characters")] + special_characters: Vec, + }, + Passphrase { + count: usize, + delimiters: Vec, + /// Path to words list. + words: String, + }, +} + +fn default_special_characters() -> Vec { + (0..128) + .map(|b| char::from_u32(b).unwrap()) + .filter(|c| c.is_ascii_graphic() && !c.is_ascii_alphanumeric()) + .collect() +} + +fn main() { + let mut rng = rand::thread_rng(); + + let mut rule_sets: HashMap = toml::from_str(&std::fs::read_to_string("rules.toml").unwrap()).unwrap(); + + let mut args = std::env::args(); + _ = args.next().unwrap(); + let rule_set_name = args.next().expect("Must specify a rule set name"); + + let password = match rule_sets.remove(&rule_set_name).unwrap() { + RuleSet::Password { length, lowercase, uppercase, numbers, special_characters } => { + let mut chars = HashSet::new(); + if lowercase { + chars.extend('a'..='z'); + } + if uppercase { + chars.extend('A'..='Z'); + } + if numbers { + chars.extend('0'..='9'); + } + chars.extend(&special_characters); + let chars = chars.into_iter().collect::>(); + + rng.sample_iter(SliceDist::new(&chars).unwrap()) + .take(length) + .collect::() + } + RuleSet::Passphrase { count, delimiters, words } => { + assert!(count > 0); + let words = std::fs::read_to_string(&words).unwrap(); + let words = words.lines().filter(|s| !s.is_empty()).collect::>(); + let words = SliceDist::new(&words).unwrap(); + let delimiters = delimiters.iter().map(char::to_string).collect::>(); + let delimiters = SliceDist::new(&delimiters).unwrap(); + let mut s = String::new(); + let mut word = rng.sample(&words); + for _ in 0..count-1 { + s.push_str(word); + word = rng.sample(&words); + s.push_str(rng.sample(&delimiters)); + } + s.push_str(word); + s + } + }; + println!("{}", password); +}