Initial Commit
This commit is contained in:
commit
ef7473a29e
5 changed files with 381 additions and 0 deletions
157
src/main.rs
Normal file
157
src/main.rs
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
use rand::{rngs::OsRng, seq::SliceRandom};
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::process;
|
||||
|
||||
static CHARACTER_SETS: [(&str, &str, &str); 10] = [
|
||||
("lowercase", "abcdefghijklmnopqrstuvwxyz", "English lowercase letters (a-z)"),
|
||||
("uppercase", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "English uppercase letters (A-Z)"),
|
||||
("numbers", "0123456789", "Numbers (0-9)"),
|
||||
("special", "!@#$%^&*()_+-=[]{}|;:,.<>?", "Special characters"),
|
||||
("special-safe", "!@#$%^&*_+-=<>?", "Safe special chars (no pipes/brackets)"),
|
||||
("cyrillic-lower", "абвгдежзийклмнопрстуфхцчшщъыьэюя", "Cyrillic lowercase"),
|
||||
("cyrillic-upper", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", "Cyrillic uppercase"),
|
||||
("greek-lower", "αβγδεζηθικλμνξοπρστυφχψω", "Greek lowercase"),
|
||||
("greek-upper", "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ", "Greek uppercase"),
|
||||
("symbols", "©®™€£¥§¶†‡•…‰′″‹›\"\'–—", "Extended symbols"),
|
||||
];
|
||||
|
||||
fn print_help() {
|
||||
println!("rs-random: Secure String Generator\n");
|
||||
println!("Usage:");
|
||||
println!(" rs-random [LENGTH] (uses safe defaults)");
|
||||
println!(" rs-random -l <LEN> [-s <SETS>] [-c <COUNT>]");
|
||||
println!(" rs-random -h | --help\n");
|
||||
println!("Available sets (for -s, comma-separated):");
|
||||
for &(name, _, desc) in &CHARACTER_SETS {
|
||||
println!(" {:<15} - {}", name, desc);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_chars(selected_sets: &[&str]) -> Result<Vec<char>, String> {
|
||||
let mut all_chars = Vec::new();
|
||||
let mut unknown = Vec::new();
|
||||
|
||||
for &set_name in selected_sets {
|
||||
match CHARACTER_SETS.iter().find(|&&(name, _, _)| name == set_name) {
|
||||
Some(&(_, chars, _)) => all_chars.extend(chars.chars()),
|
||||
None => unknown.push(set_name),
|
||||
}
|
||||
}
|
||||
|
||||
if !unknown.is_empty() {
|
||||
return Err(format!("Unknown sets: {}", unknown.join(",")));
|
||||
}
|
||||
if all_chars.is_empty() {
|
||||
return Err("Empty character pool".to_string());
|
||||
}
|
||||
|
||||
// Remove duplicates
|
||||
let mut unique_chars = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
for ch in all_chars {
|
||||
if seen.insert(ch) {
|
||||
unique_chars.push(ch);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(unique_chars)
|
||||
}
|
||||
|
||||
fn generate_random_string(chars: &[char], length: usize) -> String {
|
||||
let mut rng = OsRng;
|
||||
(0..length)
|
||||
.map(|_| *chars.choose(&mut rng).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
if args.len() < 2 || args.contains(&"-h".to_string()) || args.contains(&"--help".to_string()) {
|
||||
print_help();
|
||||
return;
|
||||
}
|
||||
|
||||
let mut length = 16;
|
||||
let mut count = 1;
|
||||
let mut sets = "lowercase,uppercase,numbers,special-safe";
|
||||
|
||||
let mut i = 1;
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"-l" | "--length" => {
|
||||
if i + 1 < args.len() {
|
||||
if let Ok(n) = args[i + 1].parse::<usize>() {
|
||||
length = n;
|
||||
} else {
|
||||
eprintln!("Error: Invalid length");
|
||||
process::exit(1);
|
||||
}
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("Error: Missing length value");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
"-s" | "--sets" => {
|
||||
if i + 1 < args.len() {
|
||||
sets = &args[i + 1];
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("Error: Missing sets value");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
"-c" | "--count" => {
|
||||
if i + 1 < args.len() {
|
||||
if let Ok(n) = args[i + 1].parse::<usize>() {
|
||||
count = n;
|
||||
} else {
|
||||
eprintln!("Error: Invalid count");
|
||||
process::exit(1);
|
||||
}
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("Error: Missing count value");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
arg if i == 1 && !arg.starts_with("-") => {
|
||||
if let Ok(n) = arg.parse::<usize>() {
|
||||
length = n;
|
||||
} else {
|
||||
eprintln!("Error: Invalid length");
|
||||
process::exit(1);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
_ => {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if length == 0 {
|
||||
eprintln!("Error: Length must be > 0");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let selected_sets: Vec<&str> = sets.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()).collect();
|
||||
|
||||
match get_chars(&selected_sets) {
|
||||
Ok(chars) => {
|
||||
for i in 0..count {
|
||||
let random_string = generate_random_string(&chars, length);
|
||||
if count > 1 {
|
||||
print!("{}: ", i + 1);
|
||||
}
|
||||
println!("{}", random_string);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue