Skip to content

Commit fa1c621

Browse files
authored
Update Login-System.py
1 parent b6c742b commit fa1c621

1 file changed

Lines changed: 145 additions & 67 deletions

File tree

20-Simple-login-system/Login-System.py

Lines changed: 145 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,170 @@
11
import tkinter as tk
22
from tkinter import messagebox
3-
import hashlib
43
import json
54
import os
5+
import re
6+
7+
from argon2 import PasswordHasher
8+
from argon2.exceptions import VerifyMismatchError
9+
10+
11+
# -------------------- Config --------------------
612

713
USER_FILE = 'users.json'
814

15+
ph = PasswordHasher(
16+
time_cost=3, # iterations
17+
memory_cost=65536, # 64 MB
18+
parallelism=4,
19+
hash_len=32,
20+
salt_len=16
21+
)
22+
23+
24+
# -------------------- Storage --------------------
25+
926
def load_users():
1027
if os.path.exists(USER_FILE):
1128
with open(USER_FILE, 'r') as f:
1229
return json.load(f)
1330
return {}
1431

32+
1533
def save_users(users):
1634
with open(USER_FILE, 'w') as f:
17-
json.dump(users, f)
35+
json.dump(users, f, indent=4)
36+
37+
38+
# -------------------- Password Security --------------------
39+
40+
def hash_password(password: str) -> str:
41+
return ph.hash(password)
42+
43+
44+
def verify_password(password: str, stored_hash: str) -> bool:
45+
try:
46+
return ph.verify(stored_hash, password)
47+
except VerifyMismatchError:
48+
return False
49+
1850

19-
def hash_password(password):
20-
return hashlib.sha256(password.encode()).hexdigest()
51+
def validate_password_strength(password: str) -> str | None:
52+
if len(password) < 12:
53+
return "Password must be at least 12 characters long"
54+
55+
if not re.search(r"[A-Z]", password):
56+
return "Password must contain an uppercase letter"
57+
58+
if not re.search(r"[a-z]", password):
59+
return "Password must contain a lowercase letter"
60+
61+
if not re.search(r"\d", password):
62+
return "Password must contain a digit"
63+
64+
if not re.search(r"[!@#$%^&*(),.?\":{}|<>]", password):
65+
return "Password must contain a special character"
66+
67+
return None
68+
69+
70+
# -------------------- App --------------------
2171

2272
class LoginApp:
2373
def __init__(self, root):
2474
self.root = root
25-
self.root.title('Modern Login System')
75+
self.root.title('Secure Login System')
2676
self.root.geometry('450x550')
2777
self.root.configure(bg='#1f2f3a')
2878
self.root.resizable(False, False)
79+
2980
self.users = load_users()
3081
self.create_login_screen()
3182

3283
def clear_screen(self):
3384
for widget in self.root.winfo_children():
3485
widget.destroy()
3586

87+
# -------------------- Login Screen --------------------
88+
3689
def create_login_screen(self):
3790
self.clear_screen()
38-
tk.Label(self.root, text='Welcome Back!', font=('Helvetica', 28, 'bold'), bg='#1f2f3a', fg='#ffffff').pack(pady=30)
39-
40-
# Username input
41-
username_frame = tk.Frame(self.root, bg='#1f2f3a')
42-
username_frame.pack(pady=10)
43-
tk.Label(username_frame, text='Username', font=('Helvetica', 12), bg='#1f2f3a', fg='#bdc3c7').pack(anchor='w')
44-
self.username_entry = tk.Entry(username_frame, font=('Helvetica', 14), bd=0, highlightthickness=2, highlightbackground='#2980b9', width=30)
45-
self.username_entry.pack(pady=5, ipady=6) # ipady increases vertical padding inside entry
46-
47-
# Password input
48-
password_frame = tk.Frame(self.root, bg='#1f2f3a')
49-
password_frame.pack(pady=10)
50-
tk.Label(password_frame, text='Password', font=('Helvetica', 12), bg='#1f2f3a', fg='#bdc3c7').pack(anchor='w')
51-
self.password_entry = tk.Entry(password_frame, font=('Helvetica', 14), bd=0, highlightthickness=2, highlightbackground='#2980b9', show='*', width=30)
52-
self.password_entry.pack(pady=5, ipady=6)
53-
54-
# Buttons
55-
btn_frame = tk.Frame(self.root, bg='#1f2f3a')
56-
btn_frame.pack(pady=20)
57-
58-
login_btn = tk.Button(btn_frame, text='Login', command=self.login, bg='#2980b9', fg='white', font=('Helvetica', 12, 'bold'), width=25, height=2, bd=0, activebackground='#3498db', cursor='hand2')
59-
login_btn.pack(pady=5)
60-
register_btn = tk.Button(btn_frame, text='Register', command=self.create_register_screen, bg='#27ae60', fg='white', font=('Helvetica', 12, 'bold'), width=25, height=2, bd=0, activebackground='#2ecc71', cursor='hand2')
61-
register_btn.pack(pady=5)
62-
forgot_btn = tk.Button(btn_frame, text='Forgot Password?', command=self.forgot_password, bg='#e67e22', fg='white', font=('Helvetica', 12, 'bold'), width=25, height=2, bd=0, activebackground='#f39c12', cursor='hand2')
63-
forgot_btn.pack(pady=5)
91+
92+
tk.Label(
93+
self.root,
94+
text='Welcome Back!',
95+
font=('Helvetica', 28, 'bold'),
96+
bg='#1f2f3a',
97+
fg='#ffffff'
98+
).pack(pady=30)
99+
100+
frame = tk.Frame(self.root, bg='#1f2f3a')
101+
frame.pack(pady=10)
102+
103+
tk.Label(frame, text='Username', fg='#bdc3c7', bg='#1f2f3a').pack(anchor='w')
104+
self.username_entry = tk.Entry(frame, font=('Helvetica', 14), width=30)
105+
self.username_entry.pack(ipady=6)
106+
107+
frame = tk.Frame(self.root, bg='#1f2f3a')
108+
frame.pack(pady=10)
109+
110+
tk.Label(frame, text='Password', fg='#bdc3c7', bg='#1f2f3a').pack(anchor='w')
111+
self.password_entry = tk.Entry(frame, font=('Helvetica', 14), show='*', width=30)
112+
self.password_entry.pack(ipady=6)
113+
114+
frame = tk.Frame(self.root, bg='#1f2f3a')
115+
frame.pack(pady=20)
116+
117+
tk.Button(frame, text='Login', height=2, width=46, command=self.login).pack(pady=5)
118+
tk.Button(frame, text='Register', height=2, width=46, command=self.create_register_screen).pack(pady=5)
119+
tk.Button(frame, text='Forgot Password?', height=2, width=46, command=self.forgot_password).pack(pady=5)
120+
121+
# -------------------- Register Screen --------------------
64122

65123
def create_register_screen(self):
66124
self.clear_screen()
67-
tk.Label(self.root, text='Create Account', font=('Helvetica', 28, 'bold'), bg='#1f2f3a', fg='#ffffff').pack(pady=30)
68-
69-
# Username
70-
username_frame = tk.Frame(self.root, bg='#1f2f3a')
71-
username_frame.pack(pady=10)
72-
tk.Label(username_frame, text='Username', font=('Helvetica', 12), bg='#1f2f3a', fg='#bdc3c7').pack(anchor='w')
73-
self.reg_username = tk.Entry(username_frame, font=('Helvetica', 14), bd=0, highlightthickness=2, highlightbackground='#27ae60', width=30)
74-
self.reg_username.pack(pady=5, ipady=6)
75-
76-
# Password
77-
password_frame = tk.Frame(self.root, bg='#1f2f3a')
78-
password_frame.pack(pady=10)
79-
tk.Label(password_frame, text='Password', font=('Helvetica', 12), bg='#1f2f3a', fg='#bdc3c7').pack(anchor='w')
80-
self.reg_password = tk.Entry(password_frame, font=('Helvetica', 14), bd=0, highlightthickness=2, highlightbackground='#27ae60', show='*', width=30)
81-
self.reg_password.pack(pady=5, ipady=6)
82-
83-
# Confirm Password
84-
confirm_frame = tk.Frame(self.root, bg='#1f2f3a')
85-
confirm_frame.pack(pady=10)
86-
tk.Label(confirm_frame, text='Confirm Password', font=('Helvetica', 12), bg='#1f2f3a', fg='#bdc3c7').pack(anchor='w')
87-
self.reg_confirm = tk.Entry(confirm_frame, font=('Helvetica', 14), bd=0, highlightthickness=2, highlightbackground='#27ae60', show='*', width=30)
88-
self.reg_confirm.pack(pady=5, ipady=6)
89-
90-
# Buttons
91-
btn_frame = tk.Frame(self.root, bg='#1f2f3a')
92-
btn_frame.pack(pady=20)
93-
94-
register_btn = tk.Button(btn_frame, text='Register', command=self.register, bg='#27ae60', fg='white', font=('Helvetica', 12, 'bold'), width=25, height=2, bd=0, activebackground='#2ecc71', cursor='hand2')
95-
register_btn.pack(pady=5)
96-
back_btn = tk.Button(btn_frame, text='Back to Login', command=self.create_login_screen, bg='#c0392b', fg='white', font=('Helvetica', 12, 'bold'), width=25, height=2, bd=0, activebackground='#e74c3c', cursor='hand2')
97-
back_btn.pack(pady=5)
125+
126+
tk.Label(
127+
self.root,
128+
text='Create Account',
129+
font=('Helvetica', 28, 'bold'),
130+
bg='#1f2f3a',
131+
fg='#ffffff'
132+
).pack(pady=30)
133+
134+
frame = tk.Frame(self.root, bg='#1f2f3a')
135+
frame.pack(pady=10)
136+
137+
tk.Label(frame, text='Username', fg='#bdc3c7', bg='#1f2f3a').pack(anchor='w')
138+
self.reg_username = tk.Entry(frame, font=('Helvetica', 14), width=30)
139+
self.reg_username.pack(ipady=6)
140+
141+
frame = tk.Frame(self.root, bg='#1f2f3a')
142+
frame.pack(pady=10)
143+
144+
tk.Label(frame, text='Password', fg='#bdc3c7', bg='#1f2f3a').pack(anchor='w')
145+
self.reg_password = tk.Entry(frame, font=('Helvetica', 14), show='*', width=30)
146+
self.reg_password.pack(ipady=6)
147+
148+
frame = tk.Frame(self.root, bg='#1f2f3a')
149+
frame.pack(pady=10)
150+
151+
tk.Label(frame, text='Confirm Password', fg='#bdc3c7', bg='#1f2f3a').pack(anchor='w')
152+
self.reg_confirm = tk.Entry(frame, font=('Helvetica', 14), show='*', width=30)
153+
self.reg_confirm.pack(ipady=6)
154+
155+
frame = tk.Frame(self.root, bg='#1f2f3a')
156+
frame.pack(pady=20)
157+
158+
tk.Button(frame, text='Register', height=2, width=46, command=self.register).pack(pady=5)
159+
tk.Button(frame, text='Back', height=2, width=46, command=self.create_login_screen).pack(pady=5)
160+
161+
# -------------------- Logic --------------------
98162

99163
def login(self):
100164
username = self.username_entry.get()
101165
password = self.password_entry.get()
102-
hashed = hash_password(password)
103-
if username in self.users and self.users[username] == hashed:
166+
167+
if username in self.users and verify_password(password, self.users[username]):
104168
messagebox.showinfo('Success', f'Welcome {username}!')
105169
else:
106170
messagebox.showerror('Error', 'Invalid username or password')
@@ -113,25 +177,39 @@ def register(self):
113177
if not username or not password:
114178
messagebox.showerror('Error', 'All fields are required')
115179
return
180+
181+
if username in self.users:
182+
messagebox.showerror('Error', 'Username already exists')
183+
return
184+
116185
if password != confirm:
117186
messagebox.showerror('Error', 'Passwords do not match')
118187
return
119-
if username in self.users:
120-
messagebox.showerror('Error', 'Username already exists')
188+
189+
strength_error = validate_password_strength(password)
190+
if strength_error:
191+
messagebox.showerror('Weak Password', strength_error)
121192
return
122193

123194
self.users[username] = hash_password(password)
124195
save_users(self.users)
196+
125197
messagebox.showinfo('Success', 'Registration successful!')
126198
self.create_login_screen()
127199

128200
def forgot_password(self):
129201
username = self.username_entry.get()
130202
if username in self.users:
131-
messagebox.showinfo('Password Reset', f'Password reset link sent to {username} (mock)')
203+
messagebox.showinfo(
204+
'Password Reset',
205+
f'Password reset link sent to {username} (mock)'
206+
)
132207
else:
133208
messagebox.showerror('Error', 'Username not found')
134209

210+
211+
# -------------------- Run --------------------
212+
135213
if __name__ == '__main__':
136214
root = tk.Tk()
137215
app = LoginApp(root)

0 commit comments

Comments
 (0)