diff --git a/Password-Generator/README.md b/Password-Generator/README.md new file mode 100644 index 0000000..2204e40 --- /dev/null +++ b/Password-Generator/README.md @@ -0,0 +1,162 @@ +# Secure Password Generator + +A secure and customizable password generator built with Python that creates cryptographically strong passwords using the `secrets` module. + +## Features + +- Generates cryptographically secure passwords +- Customizable password length (6-128 characters) +- Option to include/exclude digits and symbols +- Generates multiple passwords at once +- Save passwords to a text file +- Input validation and error handling + +## Installation + +### Prerequisites +- Python 3.6 or higher + +### Setup +1. Clone or download the `password.py` file to your local machine +2. No additional dependencies required - uses only Python's standard library + +### In Terminal +```bash +git clone https://github.com/Grow-with-Open-Source/Python-Projects.git +cd Python-Projects +cd Password-Generator +python password.py +``` + +## Usage + +Run the script from your terminal or command prompt: + +```bash +python password.py +``` + +### In your own script +```python +from password import generate_password + +# Generate a single password +password = generate_password(length=12, digits=True, symbols=True) +print(password) + +# Generate without symbols +simple_password = generate_password(length=10, digits=True, symbols=False) +print(simple_password) +``` + +## Running Examples +### Example 1: Basic Password Generation + +```python +> python password.py +Enter the length of the password: 12 +Enter the number of passwords to generate: 3 +Include digits? (y/n): y +Include symbols? (y/n): y + +Generating Secure Passwords... + +Password #1: aB3@kL9#mN2! +Password #2: pQ8$rS1^tU4* +Password #3: xY7&zW5!vZ9@ + +Do you want to save the passwords to a file? (y/n): y +Enter the name of the file (without .txt): my_passwords + +Saving passwords to file... +Passwords saved successfully! +``` + +### Example 2: Simple Alphanumeric Passwords +```python +> python password.py +Enter the length of the password: 8 +Enter the number of passwords to generate: 2 +Include digits? (y/n): y +Include symbols? (y/n): n + +Generating Secure Passwords... + +Password #1: aB3cD9eF +Password #2: gH4iJ7kL +``` + +### Example 3: Short Password (Auto-corrected) +```python +> python password.py +Enter the length of the password: 4 +Enter the number of passwords to generate: 1 +Include digits? (y/n): y +Include symbols? (y/n): y + +Password is too short - Generating Passwords of length 6 + +Generating Secure Passwords... + +Password #1: a@3b#9 +``` + +## Interactive Options +When you run the script, you'll be prompted for the following: + +1. Password Length: Enter an integer between 6 and 128 +- If you enter less than 6, it will automatically set to 6 +- Maximum length is 128 characters + +2. Number of Passwords: How many passwords to generate (positive integer) + +3. Include Digits?: (y/n) - Whether to include numbers (0-9) + +4. Include Symbols?: (y/n) - Whether to include special characters (!@#$%^&*(), etc.) + +5. Save to File?: (y/n) - Option to save generated passwords to a text file +- If yes, you can specify a filename (default: "passwords.txt") + +## Password Security Features +1. **Cryptographically Secure**: Uses ``secrets`` module (not ``random``) for true randomness + +2. **Character Variety**: Ensures at least one character from each selected character set + +3. **Shuffling**: Passwords are shuffled after generation to avoid predictable patterns + +4. **Length Enforcement**: Minimum 6 characters for basic security + +5. **Input Validation**: Validates all user inputs to prevent errors + +## File Structure +```text +password.py +├── generate_password(length, digits, symbols) # Core generator function +├── save(passwords) # File saving function +└── main() # Interactive CLI interface +``` + +## Error Handling +The script includes comprehensive error handling for: + +- Invalid integer inputs +- File system errors when saving +- Unexpected exceptions +- Length constraints and requirements + +## Limitations +- Maximum password length is 128 characters +- Minimum password length is 6 characters (enforced) +- Uses standard Python string punctuation for symbols +- Text file saving is optional and basic + +## Security Notes +- ✅ Uses secrets module for cryptographically secure random generation +- ✅ No external dependencies or network calls +- ✅ Passwords are generated locally on your machine +- ❗ Saved passwords are stored in plain text - handle with care! +- ❗ Always use strong, unique passwords for different services + +## License +This project is open-source and intended for educational and practical use. +Refer to the repository license for usage terms. \ No newline at end of file diff --git a/Password-Generator/password.py b/Password-Generator/password.py index 0dd1ae3..3347a89 100644 --- a/Password-Generator/password.py +++ b/Password-Generator/password.py @@ -1,63 +1,80 @@ -import random +import secrets +import string -def generatePassword(pwlength): - - alphabet = "abcdefghijklmnopqrstuvwxyz" - - passwords = [] - - for i in pwlength: - - password = "" - for j in range(i): - next_letter_index = random.randrange(len(alphabet)) - password = password + alphabet[next_letter_index] - - password = replaceWithNumber(password) - password = replaceWithUppercaseLetter(password) - - passwords.append(password) - - return passwords - - -def replaceWithNumber(pword): - for i in range(random.randrange(1,3)): - replace_index = random.randrange(len(pword)//2) - pword = pword[0:replace_index] + str(random.randrange(10)) + pword[replace_index+1:] - return pword - - -def replaceWithUppercaseLetter(pword): - for i in range(random.randrange(1,3)): - replace_index = random.randrange(len(pword)//2,len(pword)) - pword = pword[0:replace_index] + pword[replace_index].upper() + pword[replace_index+1:] - return pword - - - -def main(): +def generate_password(length: int = 12, digits: bool = True, symbols: bool = True) -> str: - numPasswords = int(input("How many passwords do you want to generate? ")) + min_required = int(digits) + int(symbols) + if length < min_required: + raise ValueError("Password length too small for selected options") - print("Generating " +str(numPasswords)+" passwords") + pool = string.ascii_letters + required_chars = [] - passwordLengths = [] - - print("Minimum length of password should be 3") + if digits: + pool += string.digits + required_chars.append(secrets.choice(string.digits)) - for i in range(numPasswords): - length = int(input("Enter the length of Password #" + str(i+1) + " ")) - if length<3: - length = 3 - passwordLengths.append(length) + if symbols: + pool += string.punctuation + required_chars.append(secrets.choice(string.punctuation)) + remaining_length = length - len(required_chars) - Password = generatePassword(passwordLengths) - - for i in range(numPasswords): - print ("Password #"+str(i+1)+" = " + Password[i]) - - + password = required_chars + [secrets.choice(pool) for _ in range(remaining_length)] + secrets.SystemRandom().shuffle(password) + + return ''.join(password) + +def save(passwords: list) -> None: + try: + agree: str = input("Do you want to save the passwords to a file? (y/n): ").lower().strip() + if agree not in ["y", "yes"]: + return + else: + fileName: str = input("Enter the name of the file (without .txt): ").strip() + if not fileName: + fileName: str = "passwords" + print("\nSaving passwords to file...") + with open(fileName + ".txt", "w") as f: + for password in passwords: + f.write(password + "\n") + print("Passwords saved successfully!") + except OSError as e: + print(f"Error saving passwords: {e}") + +def main() -> None: + try: + length: int = int(input("Enter the length of the password: ")) + count: int = int(input("Enter the number of passwords to generate: ")) + + if length < 1 or count < 1: + print("Please enter positive integers only.") + return + + if length > 128: + print("Password length cannot be greater than 128 characters.") + return + + if length < 6: + print("Password is too short - Generating Passwords of length 6") + length = 6 + + digits: bool = input("Include digits? (y/n): ").lower().strip() in ["y", "yes"] + symbols: bool = input("Include symbols? (y/n): ").lower().strip() in ["y", "yes"] + + print("\nGenerating Secure Passwords...\n") + passwords = [] + for i in range(count): + password = generate_password(length, digits=digits, symbols=symbols) + passwords.append(password) + print(f"Password #{i + 1}: {password}") + + save(passwords) + + except ValueError: + print("Please Enter Valid Integers Only") + except Exception as e: + print(f"An unexpected error occurred: {e}") -main() +if __name__ == "__main__": + main() \ No newline at end of file