Skip to content

Commit 5f5791c

Browse files
committed
Feat: Add CLI password manager with generation and encryption
1 parent 9eb2644 commit 5f5791c

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import random, datetime, base64, argparse, os
2+
from cryptography.fernet import Fernet
3+
4+
# 🔑 File where secret key will be stored
5+
KEY_FILE = "secret.key"
6+
7+
# ------------------------------------------------------
8+
# STEP 1: Generate a new encryption key (only once))
9+
def generate_key():
10+
key = Fernet.generate_key()
11+
with open(KEY_FILE, "wb") as f:
12+
f.write(key)
13+
14+
# STEP 2: Load the ecryption key
15+
def load_key():
16+
if not os.path.exists(KEY_FILE):
17+
print("No Key found. Creating a new one...")
18+
generate_key()
19+
with open(KEY_FILE, "rb") as f:
20+
return f.read()
21+
22+
# STEP 3: Generate password based on user settings
23+
def generate_password(length, use_lower, use_upper, use_digits, use_specials):
24+
lowercase = 'abcdefghijklmnopqrstuvwxyz'
25+
uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
26+
digits = '0123456789'
27+
specials = '!@#$%^&*()'
28+
29+
# Build character set based on user input
30+
character_set = ''
31+
32+
if use_lower:
33+
character_set = character_set + lowercase
34+
if use_upper:
35+
character_set = character_set + uppercase
36+
if use_digits:
37+
character_set = character_set + digits
38+
if use_specials:
39+
character_set = character_set + specials
40+
41+
if not character_set:
42+
return "Error: No character sets selected. Cannot generate password."
43+
44+
password = ''
45+
for i in range(length):
46+
password = password + random.choice(character_set)
47+
return password
48+
49+
# STEP 4: Check password strength
50+
def check_strength(length, use_lower, use_upper, use_digits, use_specials):
51+
score = 0
52+
53+
# Add points for character variety
54+
score = score + use_lower + use_upper + use_digits + use_specials
55+
56+
if length >= 12:
57+
score = score + 1
58+
59+
if score <= 2:
60+
return "Weak"
61+
elif score == 3 or score == 4:
62+
return "Medium"
63+
else:
64+
return "Strong"
65+
66+
# STEP 5: Command-line interface using argparse
67+
def main():
68+
parser = argparse.ArgumentParser(description="🔐 Password Generator Tool")
69+
70+
parser.add_argument('--length', type=int, required=True, help='Password length (e.g., 8, 12, 16)')
71+
parser.add_argument('--label', type=str, required=True, help='Purpose or label for the password (e.g, Google, Gmail)')
72+
parser.add_argument('--lower', action='store_true', help='Include lowercase letters')
73+
parser.add_argument('--upper', action='store_true', help='Include uppercase letters')
74+
parser.add_argument('--digits', action='store_true', help='Include digits')
75+
parser.add_argument('--specials', action='store_true', help='Include special characters')
76+
77+
args = parser.parse_args()
78+
79+
# Validate length
80+
if args.length <= 0:
81+
print("❌ Password length must be positive. Try again.")
82+
return
83+
84+
# Generate and evaluate password
85+
password = generate_password(args.length, args.lower, args.upper, args.digits, args.specials)
86+
if password.startswith("Error"):
87+
print(password)
88+
return
89+
90+
print(f"✅ Your generated password is: {password}")
91+
strength = check_strength(args.length, args.lower, args.upper, args.digits, args.specials)
92+
print(f"💪 Password Strenght: {strength}")
93+
94+
# STEP 6: Encrypt password using Fernet
95+
key = load_key()
96+
fernet = Fernet(key)
97+
encrypted_password = fernet.encrypt(password.encode()).decode() # This variable already holds the Fernet encrypted string.
98+
99+
# STEP 7: Save encrypted password to file
100+
with open("saved_passwords.txt", "a") as file:
101+
timestamp = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S")
102+
# The 'encoded_password' (base64 of original password) was being saved previously.
103+
# We should save the 'encrypted_password' (Fernet encrypted string) instead.
104+
file.write(f"\n[{timestamp}]\n")
105+
file.write(f"Label: {args.label}\n")
106+
file.write(f"Encrypted Password: {encrypted_password}\n") # Save the Fernet encrypted password and use "Encrypted Password:" label
107+
file.write(f"Included - Lowercase: {args.lower}, Uppercase: {args.upper}, Digits: {args.digits}, Special Characters: {args.specials}\n")
108+
file.write("-" * 40 + "\n")
109+
110+
print("🔒 Password encrypted and saved to 'saved_passwords.txt")
111+
112+
113+
if __name__ == '__main__':
114+
main()

0 commit comments

Comments
 (0)