import secrets
import string
import argparse
from typing import List, Optional
def generate_secure_password(
length: int = 16,
include_uppercase: bool = True,
include_lowercase: bool = True,
include_digits: bool = True,
include_symbols: bool = True,
exclude_ambiguous: bool = True
) -> str:
"""
Generate a cryptographically secure password with customizable complexity.
Args:
length: Length of the password (default: 16)
include_uppercase: Include uppercase letters (default: True)
include_lowercase: Include lowercase letters (default: True)
include_digits: Include digits (default: True)
include_symbols: Include special symbols (default: True)
exclude_ambiguous: Exclude ambiguous characters like 0, O, l, 1 (default: True)
Returns:
A secure password string
"""
if length < 4:
raise ValueError("Password length must be at least 4 characters")
# Build character set based on parameters
characters = ""
if include_uppercase:
uppercase = string.ascii_uppercase
if exclude_ambiguous:
uppercase = uppercase.replace('O', '').replace('I', '')
characters += uppercase
if include_lowercase:
lowercase = string.ascii_lowercase
if exclude_ambiguous:
lowercase = lowercase.replace('l', '').replace('o', '')
characters += lowercase
if include_digits:
digits = string.digits
if exclude_ambiguous:
digits = digits.replace('0', '').replace('1', '')
characters += digits
if include_symbols:
symbols = "!@#$%^&*()_-+=[]{}|;:,.<>?"
characters += symbols
if not characters:
raise ValueError("At least one character type must be included")
# Ensure at least one character from each selected type is included
required_chars: List[str] = []
if include_uppercase:
required_chars.append(secrets.choice(string.ascii_uppercase if not exclude_ambiguous
else string.ascii_uppercase.replace('O', '').replace('I', '')))
if include_lowercase:
required_chars.append(secrets.choice(string.ascii_lowercase if not exclude_ambiguous
else string.ascii_lowercase.replace('l', '').replace('o', '')))
if include_digits:
required_chars.append(secrets.choice(string.digits if not exclude_ambiguous
else string.digits.replace('0', '').replace('1', '')))
if include_symbols:
required_chars.append(secrets.choice("!@#$%^&*()_-+=[]{}|;:,.<>?"))
# Generate remaining characters
remaining_length = length - len(required_chars)
password_chars = required_chars + [secrets.choice(characters) for _ in range(remaining_length)]
# Shuffle the password to avoid predictable patterns
secrets.SystemRandom().shuffle(password_chars)
return ''.join(password_chars)
def main():
"""Command-line interface for password generation."""
parser = argparse.ArgumentParser(description="Generate secure passwords")
parser.add_argument("-l", "--length", type=int, default=16, help="Password length (default: 16)")
parser.add_argument("-n", "--no-uppercase", action="store_true", help="Exclude uppercase letters")
parser.add_argument("-w", "--no-lowercase", action="store_true", help="Exclude lowercase letters")
parser.add_argument("-d", "--no-digits", action="store_true", help="Exclude digits")
parser.add_argument("-s", "--no-symbols", action="store_true", help="Exclude symbols")
parser.add_argument("-a", "--allow-ambiguous", action="store_true", help="Allow ambiguous characters")
parser.add_argument("-c", "--count", type=int, default=1, help="Number of passwords to generate")
args = parser.parse_args()
try:
for i in range(args.count):
password = generate_secure_password(
length=args.length,
include_uppercase=not args.no_uppercase,
include_lowercase=not args.no_lowercase,
include_digits=not args.no_digits,
include_symbols=not args.no_symbols,
exclude_ambiguous=not args.allow_ambiguous
)
print(f"Password {i+1}: {password}")
except ValueError as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
This snippet provides a secure password generator that creates cryptographically strong passwords using Python’s secrets
module, which is designed for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, and security tokens.
The generator offers several customization options:
secrets
module instead of random
, which is cryptographically secureSave the code to a file (e.g., password_generator.py
) and run it in several ways:
python password_generator.py
Generates one 16-character password with all character types.
python password_generator.py -c 5
Generates 5 passwords.
python password_generator.py -l 20 --no-symbols -c 3
Generates 3 passwords, 20 characters long, without special symbols.
python password_generator.py -a
Generates passwords that include potentially ambiguous characters like 0 and O.
The generator ensures each password contains at least one character from each selected character type, making it both secure and compliant with most password policies.