-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimple_password_manager.py
More file actions
339 lines (263 loc) · 9.84 KB
/
simple_password_manager.py
File metadata and controls
339 lines (263 loc) · 9.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# Password Manager - Simple Version
# Author: Omar Khouja & Juan Carlos Lazo
# ReDI School Python Foundations - Final Project
# Description:
# This program helps users generate strong passwords, check password strength,
# and store passwords securely in an encrypted file.
import random
import string
import json
import hashlib
import getpass
from base64 import b64encode, b64decode
# -----------------------------
# Part 1: Password Generator
# -----------------------------
def generate_password(length=16):
"""Generate a strong random password"""
# Character sets
lowercase = string.ascii_lowercase
uppercase = string.ascii_uppercase
digits = string.digits
special = "!@#$%^&*"
# Combine all characters
all_chars = lowercase + uppercase + digits + special
# Make sure we have at least one of each type
password = [
random.choice(lowercase),
random.choice(uppercase),
random.choice(digits),
random.choice(special)
]
# Fill the rest randomly
for i in range(length - 4):
password.append(random.choice(all_chars))
# Shuffle to avoid predictable pattern
random.shuffle(password)
# Convert list to string and return
return ''.join(password)
# -----------------------------
# Part 2: Password Strength Checker
# -----------------------------
def check_password_strength(password):
"""Check how strong a password is (returns score 0-100)"""
score = 0
# Check length
if len(password) >= 12:
score += 25
elif len(password) >= 8:
score += 15
# Check for uppercase
if any(c.isupper() for c in password):
score += 20
# Check for lowercase
if any(c.islower() for c in password):
score += 20
# Check for digits
if any(c.isdigit() for c in password):
score += 20
# Check for special characters
if any(c in "!@#$%^&*" for c in password):
score += 15
# Return score and rating
if score >= 80:
rating = "Very Strong"
elif score >= 60:
rating = "Strong"
elif score >= 40:
rating = "Medium"
else:
rating = "Weak"
return score, rating
# -----------------------------
# Part 3: Simple Encryption (using password as key)
# -----------------------------
def simple_encrypt(text, master_password):
"""Encrypt text using master password"""
# Create a key from password using hash
key = hashlib.sha256(master_password.encode()).digest()
# Simple XOR encryption
encrypted = []
for i, char in enumerate(text):
key_char = key[i % len(key)]
encrypted_char = chr(ord(char) ^ key_char)
encrypted.append(encrypted_char)
# Encode to base64 to make it printable
encrypted_text = ''.join(encrypted)
return b64encode(encrypted_text.encode()).decode()
def simple_decrypt(encrypted_text, master_password):
"""Decrypt text using master password"""
try:
# Decode from base64
encrypted_text = b64decode(encrypted_text.encode()).decode()
# Create same key from password
key = hashlib.sha256(master_password.encode()).digest()
# Decrypt using XOR
decrypted = []
for i, char in enumerate(encrypted_text):
key_char = key[i % len(key)]
decrypted_char = chr(ord(char) ^ key_char)
decrypted.append(decrypted_char)
return ''.join(decrypted)
except:
return None
# -----------------------------
# Part 4: Storage (save/load passwords)
# -----------------------------
def save_passwords(passwords, master_password):
"""Save passwords to file (encrypted)"""
# Convert passwords list to JSON string
json_text = json.dumps(passwords, indent=2)
# Encrypt the JSON
encrypted = simple_encrypt(json_text, master_password)
# Save to file
with open("passwords.txt", "w") as file:
file.write(encrypted)
print("✓ Passwords saved!")
def load_passwords(master_password):
"""Load passwords from file (decrypt)"""
try:
# Read encrypted file
with open("passwords.txt", "r") as file:
encrypted = file.read()
# Decrypt
json_text = simple_decrypt(encrypted, master_password)
if json_text is None:
print("✗ Wrong master password!")
return None
# Convert JSON back to list
passwords = json.loads(json_text)
return passwords
except FileNotFoundError:
# File doesn't exist yet - return empty list
return []
# -----------------------------
# Part 5: Main Program (Menu)
# -----------------------------
def change_master_password(passwords, old_master_password):
"""Change the master password"""
print("\n" + "=" * 50)
print("CHANGE MASTER PASSWORD")
print("=" * 50)
# Ask for new master password
new_password = getpass.getpass("\n🔑 Enter NEW master password: ")
confirm_password = getpass.getpass("🔑 Confirm NEW master password: ")
# Check if they match
if new_password != confirm_password:
print("✗ Passwords don't match!")
return old_master_password
# Check strength of new password
score, rating = check_password_strength(new_password)
print(f"\nNew password strength: {rating} ({score}/100)")
if score < 60:
confirm = input("\n⚠️ Warning: Password is not very strong. Continue? (yes/no): ")
if confirm.lower() != "yes":
print("Cancelled.")
return old_master_password
# Save with new master password
save_passwords(passwords, new_password)
print("\n✓ Master password changed successfully!")
print("⚠️ Remember your new password - it cannot be recovered!")
return new_password
def main():
print("=" * 50)
print("PASSWORD MANAGER - Simple Version")
print("=" * 50)
# Ask for master password
master_password = getpass.getpass("\n🔑 Enter master password: ")
# Load existing passwords
passwords = load_passwords(master_password)
if passwords is None:
print("Exiting...")
return
print(f"\n✓ Loaded {len(passwords)} password(s)")
# Main menu loop
while True:
print("\n" + "-" * 50)
print("MENU")
print("-" * 50)
print("1. Generate new password")
print("2. Check password strength")
print("3. Add password to vault")
print("4. View all passwords")
print("5. Search password")
print("6. Change master password")
print("7. Exit")
print("-" * 50)
choice = input("\nChoose (1-7): ")
if choice == "1":
# Generate password
print("\n--- PASSWORD GENERATOR ---")
length = input("Password length (default 16): ")
length = int(length) if length.isdigit() else 16
# Generate 5 options
print(f"\nGenerated passwords:\n")
for i in range(5):
pwd = generate_password(length)
score, rating = check_password_strength(pwd)
print(f"{i+1}. {pwd} [{rating}]")
elif choice == "2":
# Check strength
print("\n--- PASSWORD STRENGTH CHECKER ---")
pwd = getpass.getpass("Enter password to check: ")
score, rating = check_password_strength(pwd)
print(f"\nStrength: {rating} (Score: {score}/100)")
elif choice == "3":
# Add password
print("\n--- ADD PASSWORD ---")
website = input("Website/App: ")
username = input("Username: ")
print("\n1. Generate new password")
print("2. Enter my own password")
opt = input("Choose (1/2): ")
if opt == "1":
password = generate_password()
print(f"Generated: {password}")
else:
password = getpass.getpass("Password: ")
# Add to list
passwords.append({
"website": website,
"username": username,
"password": password
})
# Save
save_passwords(passwords, master_password)
print("✓ Password added!")
elif choice == "4":
# View all
print("\n--- ALL PASSWORDS ---")
if len(passwords) == 0:
print("No passwords saved yet.")
else:
for i, p in enumerate(passwords, 1):
print(f"\n{i}. {p['website']}")
print(f" Username: {p['username']}")
print(f" Password: {p['password']}")
elif choice == "5":
# Search
print("\n--- SEARCH ---")
query = input("Search website/username: ").lower()
found = False
for p in passwords:
if query in p['website'].lower() or query in p['username'].lower():
print(f"\nWebsite: {p['website']}")
print(f"Username: {p['username']}")
print(f"Password: {p['password']}")
found = True
if not found:
print("No matching passwords found.")
elif choice == "6":
# Change master password
master_password = change_master_password(passwords, master_password)
elif choice == "7":
# Exit
print("\nGoodbye! Your passwords are safe.")
break
else:
print("Invalid choice!")
# -----------------------------
# Run the program
# -----------------------------
if __name__ == "__main__":
main()