hassan773 commited on
Commit
0c7a588
Β·
verified Β·
1 Parent(s): d536884

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -26
app.py CHANGED
@@ -8,27 +8,37 @@ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
8
 
9
  # File where encrypted data is stored
10
  VAULT_FILE = "passwords.json"
 
 
11
 
12
- # --- Encryption Logic ---
13
 
14
  def get_cipher(master_password):
15
- salt = b'nutech_hassan_salt_123'
 
 
16
  kdf = PBKDF2HMAC(
17
  algorithm=hashes.SHA256(),
18
  length=32,
19
  salt=salt,
20
- iterations=100000,
21
  )
22
  key = base64.urlsafe_b64encode(kdf.derive(master_password.encode()))
23
  return Fernet(key)
24
 
25
  def process_vault(action, master_pwd, service=None, secret=None):
 
 
 
 
 
26
  if not master_pwd:
27
- return "⚠️ Please enter your Master Password first!"
28
 
29
  try:
30
  cipher = get_cipher(master_pwd)
31
 
 
32
  if os.path.exists(VAULT_FILE):
33
  with open(VAULT_FILE, "r") as f:
34
  vault = json.load(f)
@@ -38,59 +48,75 @@ def process_vault(action, master_pwd, service=None, secret=None):
38
  if action == "Save":
39
  if not service or not secret:
40
  return "⚠️ Service name and Password are required!"
 
 
41
  encrypted_data = cipher.encrypt(secret.encode()).decode()
42
  vault[service] = encrypted_data
 
43
  with open(VAULT_FILE, "w") as f:
44
  json.dump(vault, f)
45
- return f"βœ… Successfully encrypted and saved password for {service}."
 
 
46
 
47
  elif action == "Retrieve":
48
  if not service:
49
- return "⚠️ Enter a service name to search."
50
  if service not in vault:
51
  return f"❌ No record found for '{service}'."
 
 
52
  decrypted_data = cipher.decrypt(vault[service].encode()).decode()
 
 
53
  return f"πŸ”‘ Password for {service}: {decrypted_data}"
54
 
55
  except Exception:
56
- return "🚫 Access Denied: Incorrect Master Password or corrupted data."
 
 
57
 
58
- # --- UI Setup ---
59
 
60
  custom_css = """
61
- .gradio-container { max-width: 700px; margin: auto; }
62
- .header-text { text-align: center; margin-bottom: 20px; }
 
 
 
 
63
  """
64
 
65
  with gr.Blocks() as demo:
66
  gr.HTML("""
67
- <div class="header-text">
68
- <h1 style="display:inline;">πŸ” SecureVault Manager</h1>
69
- <span style="font-size: 14px; color: grey;"> | Developed by Hassan Naseer</span>
70
  </div>
71
  """)
72
 
73
  with gr.Row():
74
  master_key = gr.Textbox(
75
- label="Master Password",
76
  type="password",
77
- placeholder="Enter your Master Password to unlock"
78
  )
79
 
80
  with gr.Tabs():
81
- with gr.Tab(label="βž• Add New"):
82
- svc = gr.Textbox(label="Service Name", placeholder="e.g., GitHub")
83
- pwd = gr.Textbox(label="Password", type="password", placeholder="Enter password")
84
- save_btn = gr.Button("Encrypt & Save", variant="primary")
 
85
 
86
- with gr.Tab(label="πŸ” Retrieve"):
87
- search_svc = gr.Textbox(label="Service Name", placeholder="e.g., GitHub")
88
- get_btn = gr.Button("Decrypt & Reveal", variant="secondary")
 
89
 
90
- status_output = gr.Textbox(label="Vault Status", interactive=False)
91
 
92
- # --- FIXED EVENT HANDLERS ---
93
- # We use lambda to pass the "Save" and "Retrieve" strings correctly
94
  save_btn.click(
95
  fn=lambda m, s, p: process_vault("Save", m, s, p),
96
  inputs=[master_key, svc, pwd],
@@ -104,4 +130,5 @@ with gr.Blocks() as demo:
104
  )
105
 
106
  if __name__ == "__main__":
107
- demo.launch(css=custom_css)
 
 
8
 
9
  # File where encrypted data is stored
10
  VAULT_FILE = "passwords.json"
11
+ FAILED_ATTEMPTS = 0
12
+ MAX_ATTEMPTS = 5
13
 
14
+ # --- Core Security Logic ---
15
 
16
  def get_cipher(master_password):
17
+ """Derives a strong AES-256 key from the master password."""
18
+ # Salt adds randomness to the key derivation
19
+ salt = b'hassan_naseer_secure_salt_2026'
20
  kdf = PBKDF2HMAC(
21
  algorithm=hashes.SHA256(),
22
  length=32,
23
  salt=salt,
24
+ iterations=150000, # Increased iterations for better security
25
  )
26
  key = base64.urlsafe_b64encode(kdf.derive(master_password.encode()))
27
  return Fernet(key)
28
 
29
  def process_vault(action, master_pwd, service=None, secret=None):
30
+ global FAILED_ATTEMPTS
31
+
32
+ if FAILED_ATTEMPTS >= MAX_ATTEMPTS:
33
+ return "πŸ›‘ SECURITY LOCKOUT: Too many failed attempts. Access disabled."
34
+
35
  if not master_pwd:
36
+ return "⚠️ Master Password required to access Vault."
37
 
38
  try:
39
  cipher = get_cipher(master_pwd)
40
 
41
+ # Load the encrypted vault
42
  if os.path.exists(VAULT_FILE):
43
  with open(VAULT_FILE, "r") as f:
44
  vault = json.load(f)
 
48
  if action == "Save":
49
  if not service or not secret:
50
  return "⚠️ Service name and Password are required!"
51
+
52
+ # Encrypt the password before saving
53
  encrypted_data = cipher.encrypt(secret.encode()).decode()
54
  vault[service] = encrypted_data
55
+
56
  with open(VAULT_FILE, "w") as f:
57
  json.dump(vault, f)
58
+
59
+ FAILED_ATTEMPTS = 0 # Reset on success
60
+ return f"βœ… Encrypted & Saved: {service}"
61
 
62
  elif action == "Retrieve":
63
  if not service:
64
+ return "⚠️ Enter a service name to decrypt."
65
  if service not in vault:
66
  return f"❌ No record found for '{service}'."
67
+
68
+ # Decrypt the password
69
  decrypted_data = cipher.decrypt(vault[service].encode()).decode()
70
+
71
+ FAILED_ATTEMPTS = 0 # Reset on success
72
  return f"πŸ”‘ Password for {service}: {decrypted_data}"
73
 
74
  except Exception:
75
+ FAILED_ATTEMPTS += 1
76
+ remaining = MAX_ATTEMPTS - FAILED_ATTEMPTS
77
+ return f"🚫 Access Denied! {remaining} attempts remaining."
78
 
79
+ # --- UI Styling ---
80
 
81
  custom_css = """
82
+ .gradio-container { max-width: 750px; margin: auto; padding: 20px; }
83
+ .header-box { text-align: center; margin-bottom: 25px; border-bottom: 1px solid #ddd; padding-bottom: 10px; }
84
+ @media (max-width: 768px) {
85
+ .gradio-container { padding: 10px; }
86
+ h1 { font-size: 1.5em !important; }
87
+ }
88
  """
89
 
90
  with gr.Blocks() as demo:
91
  gr.HTML("""
92
+ <div class="header-box">
93
+ <h1 style="display:inline; color: #2d3436;">πŸ” SecureVault Manager</h1>
94
+ <p style="font-size: 0.9em; color: #636e72;">Developed by Hassan Naseer | AES-256 Encryption</p>
95
  </div>
96
  """)
97
 
98
  with gr.Row():
99
  master_key = gr.Textbox(
100
+ label="Unlock Vault with Master Password",
101
  type="password",
102
+ placeholder="Enter Master Password..."
103
  )
104
 
105
  with gr.Tabs():
106
+ with gr.Tab(label="πŸ“₯ Add Password"):
107
+ with gr.Column():
108
+ svc = gr.Textbox(label="Service", placeholder="e.g., Google, Bank, GitHub")
109
+ pwd = gr.Textbox(label="Password to Protect", type="password")
110
+ save_btn = gr.Button("πŸ”’ Encrypt & Store", variant="primary")
111
 
112
+ with gr.Tab(label="πŸ”“ Retrieve Password"):
113
+ with gr.Column():
114
+ search_svc = gr.Textbox(label="Service Name", placeholder="Enter service to search")
115
+ get_btn = gr.Button("πŸ”‘ Decrypt & Show", variant="secondary")
116
 
117
+ status_output = gr.Textbox(label="Operation Status", interactive=False)
118
 
119
+ # --- Event Handlers using Lambda to fix the AttributeError ---
 
120
  save_btn.click(
121
  fn=lambda m, s, p: process_vault("Save", m, s, p),
122
  inputs=[master_key, svc, pwd],
 
130
  )
131
 
132
  if __name__ == "__main__":
133
+ # Launch with Gradio 6 compatibility
134
+ demo.launch(css=custom_css, title="SecureVault | Hassan Naseer")