Rust LogoPassword Generator

A password generator is a software tool designed to create strong, random, and unique passwords that are difficult for humans or computers to guess. In an era where digital security is paramount, strong passwords serve as the first line of defense against unauthorized access to accounts and data breaches.

The primary goal of a password generator is to produce passwords that exhibit high entropy, meaning they are unpredictable. This is achieved by:
1. Length: Longer passwords are exponentially harder to crack. Most generators allow users to specify the desired length.
2. Character Variety: Strong passwords typically incorporate a mix of character types:
* Lowercase letters: (a-z)
* Uppercase letters: (A-Z)
* Numbers: (0-9)
* Symbols/Special characters: (!@#$%^&*()_+-=[]{}|;':",.<>/?`~)

How it works:
A typical password generator works by defining character pools for each type (e.g., one string for all lowercase letters, another for uppercase, etc.). When a user requests a password of a certain length and with specific character types included, the generator combines the selected character pools into a single large pool. It then repeatedly selects characters at random from this combined pool until the desired password length is reached. To ensure at least one character of each selected type is present (if required and feasible), some generators might first pick one character from each required pool and then fill the rest of the length randomly from the combined pool, finally shuffling the entire password to randomize character positions.

Benefits of using a password generator include:
* Enhanced Security: Randomly generated passwords eliminate human biases and patterns often found in user-created passwords (like birthdays, names, common words).
* Uniqueness: Encourages the use of unique passwords for each service, preventing a "domino effect" if one service is compromised.
* Convenience: Quickly generates complex passwords without needing to manually devise them.

It's crucial to pair the use of a password generator with a robust password manager to securely store and retrieve these complex, unique passwords.

Example Code

# Add the 'rand' crate to your Cargo.toml file:
# [dependencies]
# rand = "0.8"

use rand::seq::SliceRandom;
use rand::Rng; // For thread_rng

/// Generates a random password based on specified criteria.
///
/// # Arguments
/// * `length` - The desired length of the password.
/// * `include_uppercase` - Whether to include uppercase letters (A-Z).
/// * `include_lowercase` - Whether to include lowercase letters (a-z).
/// * `include_numbers` - Whether to include numbers (0-9).
/// * `include_symbols` - Whether to include special characters (!@#$%^&*()_+-=[]{}|;:',.<>/?`~).
///
/// # Returns
/// A `String` containing the generated password or an error message if
/// no character types are selected or the length is too short for all guarantees.
fn generate_password(
    length: usize,
    include_uppercase: bool,
    include_lowercase: bool,
    include_numbers: bool,
    include_symbols: bool,
) -> String {
    let lowercase_chars = "abcdefghijklmnopqrstuvwxyz";
    let uppercase_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    let number_chars = "0123456789";
    let symbol_chars = "!@#$%^&*()_+-=[]{}|;:',.<>/?`~";

    let mut available_chars = String::new();
    let mut ensured_chars_pool = Vec::new(); // To store pools for ensuring char types

    if include_lowercase {
        available_chars.push_str(lowercase_chars);
        ensured_chars_pool.push(lowercase_chars);
    }
    if include_uppercase {
        available_chars.push_str(uppercase_chars);
        ensured_chars_pool.push(uppercase_chars);
    }
    if include_numbers {
        available_chars.push_str(number_chars);
        ensured_chars_pool.push(number_chars);
    }
    if include_symbols {
        available_chars.push_str(symbol_chars);
        ensured_chars_pool.push(symbol_chars);
    }

    // Handle case where no character types are selected
    if available_chars.is_empty() {
        return String::from("Error: No character types selected to generate password.");
    }

    // If there are more types to ensure than the desired length, we can't fulfill all guarantees.
    if ensured_chars_pool.len() > length {
        return String::from("Error: Desired length is too short to include at least one of each selected character type.");
    }

    let all_chars_vec: Vec<char> = available_chars.chars().collect();
    let mut password_chars: Vec<char> = Vec::with_capacity(length);
    let mut rng = rand::thread_rng();

    // Ensure at least one character of each selected type
    for pool_str in ensured_chars_pool {
        if let Some(c) = pool_str.chars().collect::<Vec<char>>().choose(&mut rng) {
            password_chars.push(*c);
        }
    }

    // Fill the rest of the password length randomly from the combined pool
    for _ in 0..(length - password_chars.len()) {
        if let Some(c) = all_chars_vec.choose(&mut rng) {
            password_chars.push(*c);
        }
    }

    // Shuffle the password to mix the ensured characters randomly
    password_chars.shuffle(&mut rng);

    password_chars.iter().collect()
}

fn main() {
    println!("--- Password Generator ---");

    // Example 1: Standard strong password (16 chars, all types)
    let password_1 = generate_password(16, true, true, true, true);
    println!("Password 1 (16 chars, all types): {}", password_1);

    // Example 2: Medium length, no symbols (12 chars)
    let password_2 = generate_password(12, true, true, true, false);
    println!("Password 2 (12 chars, no symbols): {}", password_2);

    // Example 3: Long password, only letters and numbers (20 chars)
    let password_3 = generate_password(20, true, true, true, false);
    println!("Password 3 (20 chars, letters+numbers): {}", password_3);

    // Example 4: Short, only lowercase (8 chars)
    let password_4 = generate_password(8, false, true, false, false);
    println!("Password 4 (8 chars, lowercase only): {}", password_4);

    // Example 5: Error case - no types selected (10 chars)
    let password_5 = generate_password(10, false, false, false, false);
    println!("Password 5 (10 chars, no types selected): {}", password_5);

    // Example 6: Error case - length too short for all guarantees (3 chars, all types)
    let password_6 = generate_password(3, true, true, true, true); // Tries to ensure 4 types in 3 chars
    println!("Password 6 (3 chars, all types): {}", password_6);
}