Vishnu Naresh Boddeti commited on
Commit
f5a949f
·
1 Parent(s): 06a7ef6

minor updates

Browse files
Files changed (1) hide show
  1. app.py +132 -41
app.py CHANGED
@@ -16,6 +16,7 @@ EXAMPLE_IMAGES_AUTH = ['./VGGFace2/n000001/0013_01.jpg', './VGGFace2/n000149/001
16
 
17
  # --- Global Variables ---
18
  face_app = None
 
19
 
20
  # --- Helper Functions ---
21
  def initialize_face_app():
@@ -37,7 +38,13 @@ def run_binary(bin_path, *args):
37
  command = [bin_path] + list(args)
38
  print(f"Running command: {' '.join(command)}")
39
 
40
- cwd = "."
 
 
 
 
 
 
41
 
42
  try:
43
  os.chmod(bin_path, 0o755)
@@ -157,14 +164,19 @@ body, .gradio-container { background: var(--background); color: var(--foreground
157
  with gr.Blocks(css=css) as demo:
158
  # --- Header ---
159
  gr.HTML("""
160
- <div class="main-header">
161
- <img src="./static/logo.png" alt="Suraksh.AI Logo" style="height: 60px; margin-bottom: 1rem;">
162
  <h1>Suraksh AI</h1>
163
  <p style="color: #EEEEEC; opacity: 0.9;">The Future of Secure Biometrics</p>
164
  <a href="https://suraksh.ai/" target="_blank">🌐 Visit Our Website</a>
165
  </div>
166
  """)
167
 
 
 
 
 
 
 
168
  # --- Main Tabs for Demo Mode ---
169
  with gr.Tabs() as mode_tabs:
170
  # --- 1:1 Recognition Demo ---
@@ -177,15 +189,50 @@ with gr.Blocks(css=css) as demo:
177
  with gr.Group(elem_classes="narrative-section"):
178
  gr.HTML('<h2 class="narrative-header">The Problem: How Your Face Can Be Stolen</h2>')
179
  gr.HTML("""<div class="warning-card"><h3>⚠️ Your Biometric Data is Exposed!</h3><p>Most systems handle biometric data in plaintext. This means your facial embedding—a digital map of your face—can be stolen and used to reconstruct your image, creating a major privacy risk.</p></div>""")
180
- with gr.Row():
181
- with gr.Column():
182
- vuln_image_in = create_image_selection_ui("1. Select an Image", EXAMPLE_IMAGES_ENROLL)
183
- with gr.Column():
184
- gr.HTML('<h3 class="step-header">2. Reconstruct the Face</h3><p>Click below to simulate an attacker stealing the embedding and recreating the face.</p>')
185
- reconstruct_btn = gr.Button("😱 Reconstruct My Face!", variant="stop")
186
- vuln_image_out = gr.Image(type="filepath", label="Reconstructed Face", interactive=False)
187
 
188
- reconstruct_btn.click(lambda x: "./static/reconstructed.png" if x else None, inputs=vuln_image_in, outputs=vuln_image_out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  # --- Secure System Tab ---
191
  with gr.TabItem("✅ The Suraksh.AI Solution"):
@@ -196,8 +243,14 @@ with gr.Blocks(css=css) as demo:
196
  with gr.Row():
197
  with gr.Column():
198
  rec_ref_img = create_image_selection_ui("1. Provide Reference Image", EXAMPLE_IMAGES_ENROLL)
 
 
 
199
  with gr.Column():
200
  rec_probe_img = create_image_selection_ui("2. Provide Probe Image", EXAMPLE_IMAGES_AUTH)
 
 
 
201
 
202
  with gr.Accordion("Advanced Settings", open=False):
203
  rec_threshold = gr.Slider(-512*5, 512*5, value=133, label="Match Strictness", info="A higher value means a stricter match is required.")
@@ -209,29 +262,43 @@ with gr.Blocks(css=css) as demo:
209
  rec_result = gr.HTML()
210
 
211
  def secure_recognition_flow(ref_img, probe_img, threshold, sec_level):
212
- yield "Initializing...", ""
213
- bin_path = "./bin/genKeys.bin"
214
- run_binary(bin_path, sec_level, "genkeys")
215
- yield "✅ Keys Generated... Encrypting Reference...", ""
216
- _, _ = extract_embedding(ref_img, "enroll")
 
 
 
217
  run_binary("./bin/encReference.bin", sec_level, "encrypt")
218
- yield "✅ Reference Encrypted... Encrypting Probe...", ""
219
- _, _ = extract_embedding(probe_img, "auth")
 
 
 
 
 
 
220
  run_binary("./bin/encProbe.bin", sec_level, "encrypt")
221
- yield "✅ Probe Encrypted... Performing Secure Match...", ""
 
 
 
222
  run_binary("./bin/recDecision.bin", sec_level, "decision", str(threshold))
223
- yield "✅ Match Computed... Decrypting Result...", ""
 
224
  output, _ = run_binary("./bin/decDecision.bin", sec_level, "decision")
 
225
  if "match" in output.lower():
226
  result_html = """<div class="result-container match-verified"><h2>✅ MATCH VERIFIED</h2><p>Identity successfully confirmed under FHE.</p></div>"""
227
  else:
228
  result_html = """<div class="result-container no-match"><h2>❌ NO MATCH</h2><p>Identity verification failed.</p></div>"""
229
- yield "Done!", result_html
230
 
231
  rec_run_btn.click(
232
  fn=secure_recognition_flow,
233
  inputs=[rec_ref_img, rec_probe_img, rec_threshold, rec_sec_level],
234
- outputs=[rec_status, rec_result]
235
  )
236
 
237
  # --- 1:N Search Demo ---
@@ -247,13 +314,21 @@ with gr.Blocks(css=css) as demo:
247
 
248
  with gr.Row():
249
  with gr.Column():
250
- search_enroll_img = create_image_selection_ui("1. Enroll Subjects into DB", EXAMPLE_IMAGES_ENROLL)
251
- search_offset = gr.Number(label="Subject Offset ID", info="A unique ID for this person in the DB.", precision=0)
252
  search_enroll_btn = gr.Button("➕ Encrypt & Add to Database", variant="secondary")
 
 
 
253
  search_enroll_status = gr.HTML()
 
254
  with gr.Column():
255
- search_probe_img = create_image_selection_ui("2. Search for a Subject", EXAMPLE_IMAGES_AUTH)
 
256
  search_run_btn = gr.Button("🚀 Perform Secure 1:N Search", variant="primary", size="lg")
 
 
 
257
  search_status = gr.HTML(elem_classes="status-text")
258
 
259
  search_result = gr.HTML()
@@ -262,41 +337,57 @@ with gr.Blocks(css=css) as demo:
262
  search_threshold = gr.Slider(-512*5, 512*5, value=133, label="Match Strictness")
263
  search_sec_level = gr.Dropdown(SECURITYLEVELS, value="128", label="Security Level")
264
 
265
- demo.load(lambda: run_binary("./bin/search.bin", "128", "genkeys"), None, None)
266
-
267
- def secure_enroll_flow(image, offset, sec_level):
268
- if image is None or offset is None: raise gr.Error("Please provide an image and a unique offset ID.")
269
- yield "Encrypting and adding subject..."
270
- _, emb_path = extract_embedding(image, "search_enroll")
271
- run_binary("./bin/search.bin", sec_level, "encRef", emb_path, str(int(offset)))
 
 
 
 
 
 
 
272
  run_binary("./bin/search.bin", sec_level, "addRef")
273
- yield f"✅ Subject with ID {int(offset)} added to the secure database."
 
 
274
 
275
  def secure_search_flow(image, threshold, sec_level):
276
  if image is None: raise gr.Error("Please provide an image to search.")
277
- yield "Initializing secure search...", ""
278
- _, emb_path = extract_embedding(image, "search_auth")
 
 
 
279
  run_binary("./bin/search.bin", sec_level, "encProbe", emb_path)
280
- yield "✅ Probe encrypted... Searching database...", ""
 
 
281
  run_binary("./bin/search.bin", sec_level, "search")
282
- yield "✅ Search complete... Decrypting results...", ""
 
283
  output, _ = run_binary("./bin/search.bin", sec_level, "decDecisionClear", str(threshold))
 
284
  if "found" in output.lower():
285
  result_html = """<div class="result-container match-verified"><h2>✅ SUBJECT FOUND</h2><p>The subject was successfully found in the database.</p></div>"""
286
  else:
287
  result_html = """<div class="result-container no-match"><h2>❌ NOT FOUND</h2><p>The subject was not found in the database.</p></div>"""
288
- yield "Done!", result_html
289
 
290
  search_enroll_btn.click(
291
  fn=secure_enroll_flow,
292
- inputs=[search_enroll_img, search_offset, search_sec_level],
293
- outputs=[search_enroll_status]
294
  )
295
 
296
  search_run_btn.click(
297
  fn=secure_search_flow,
298
  inputs=[search_probe_img, search_threshold, search_sec_level],
299
- outputs=[search_status, search_result]
300
  )
301
 
302
  # --- Launch the Application ---
 
16
 
17
  # --- Global Variables ---
18
  face_app = None
19
+ DB_SUBJECT_COUNT = 0
20
 
21
  # --- Helper Functions ---
22
  def initialize_face_app():
 
38
  command = [bin_path] + list(args)
39
  print(f"Running command: {' '.join(command)}")
40
 
41
+ # Determine working directory based on binary path
42
+ if "biometric-recognition-FHE" in bin_path:
43
+ cwd = "./biometric-recognition-FHE"
44
+ elif "biometric-search-FHE" in bin_path:
45
+ cwd = "./biometric-search-FHE"
46
+ else:
47
+ cwd = "."
48
 
49
  try:
50
  os.chmod(bin_path, 0o755)
 
164
  with gr.Blocks(css=css) as demo:
165
  # --- Header ---
166
  gr.HTML("""
167
+ <div class="main-header">
 
168
  <h1>Suraksh AI</h1>
169
  <p style="color: #EEEEEC; opacity: 0.9;">The Future of Secure Biometrics</p>
170
  <a href="https://suraksh.ai/" target="_blank">🌐 Visit Our Website</a>
171
  </div>
172
  """)
173
 
174
+ # --- Key Generation on Load ---
175
+ # Generate keys once for each demo when the app starts up
176
+ demo.load(lambda: run_binary("./bin/genKeys.bin", "128", "genkeys"), None, None)
177
+ demo.load(lambda: run_binary("./bin/search.bin", "128", "genkeys"), None, None)
178
+
179
+
180
  # --- Main Tabs for Demo Mode ---
181
  with gr.Tabs() as mode_tabs:
182
  # --- 1:1 Recognition Demo ---
 
189
  with gr.Group(elem_classes="narrative-section"):
190
  gr.HTML('<h2 class="narrative-header">The Problem: How Your Face Can Be Stolen</h2>')
191
  gr.HTML("""<div class="warning-card"><h3>⚠️ Your Biometric Data is Exposed!</h3><p>Most systems handle biometric data in plaintext. This means your facial embedding—a digital map of your face—can be stolen and used to reconstruct your image, creating a major privacy risk.</p></div>""")
 
 
 
 
 
 
 
192
 
193
+ with gr.Column():
194
+ gr.HTML('<h3 class="step-header">1. Original Image</h3>')
195
+ gr.Image(value=EXAMPLE_IMAGES_ENROLL[2], label="Original Face", interactive=False, show_label=False, container=False)
196
+
197
+ gr.HTML('<h3 class="step-header" style="margin-top: 2rem;">2. Simulate Attack: Steal Data</h3><p>An attacker breaches the system and steals the stored facial embedding. Click the button to simulate this theft.</p>')
198
+ extract_btn = gr.Button("😱 Steal Biometric Data", variant="primary")
199
+
200
+ with gr.Group(visible=False) as stolen_data_group:
201
+ feature_output = gr.JSON(label="Stolen Feature Vector (Face Embedding)")
202
+ gr.HTML('<h3 class="step-header" style="margin-top: 2rem;">3. Simulate Attack: Reconstruct Face</h3><p>Now, the attacker uses the stolen features to create a reconstruction of the face, completely compromising the user\'s privacy.</p>')
203
+ reconstruct_btn = gr.Button("🎭 Reconstruct Face from Stolen Data", variant="stop")
204
+
205
+ with gr.Group(visible=False) as reconstructed_image_group:
206
+ reconstructed_output = gr.Image(label="Reconstructed Face", interactive=False, show_label=False)
207
+
208
+ def extract_and_reveal(image_path):
209
+ embedding = extract_embedding(image_path)
210
+ feature_json = {"embedding": embedding}
211
+ return {
212
+ feature_output: feature_json,
213
+ stolen_data_group: gr.update(visible=True),
214
+ extract_btn: gr.update(value="Data Stolen!", interactive=False)
215
+ }
216
+
217
+ def show_reconstruction():
218
+ reconstructed_image_path = "./static/reconstructed.png"
219
+ return {
220
+ reconstructed_output: reconstructed_image_path,
221
+ reconstructed_image_group: gr.update(visible=True),
222
+ reconstruct_btn: gr.update(interactive=False)
223
+ }
224
+
225
+ extract_btn.click(
226
+ fn=extract_and_reveal,
227
+ inputs=gr.State(EXAMPLE_IMAGES_ENROLL[0]),
228
+ outputs=[feature_output, stolen_data_group, extract_btn]
229
+ )
230
+
231
+ reconstruct_btn.click(
232
+ fn=show_reconstruction,
233
+ inputs=None,
234
+ outputs=[reconstructed_output, reconstructed_image_group, reconstruct_btn]
235
+ )
236
 
237
  # --- Secure System Tab ---
238
  with gr.TabItem("✅ The Suraksh.AI Solution"):
 
243
  with gr.Row():
244
  with gr.Column():
245
  rec_ref_img = create_image_selection_ui("1. Provide Reference Image", EXAMPLE_IMAGES_ENROLL)
246
+ with gr.Group(visible=False) as rec_ref_features_group:
247
+ rec_ref_raw_features = gr.JSON(label="Raw Features (Plaintext)")
248
+ rec_ref_encrypted_features = gr.Textbox(label="Encrypted Features (Ciphertext)", interactive=False, lines=5)
249
  with gr.Column():
250
  rec_probe_img = create_image_selection_ui("2. Provide Probe Image", EXAMPLE_IMAGES_AUTH)
251
+ with gr.Group(visible=False) as rec_probe_features_group:
252
+ rec_probe_raw_features = gr.JSON(label="Raw Features (Plaintext)")
253
+ rec_probe_encrypted_features = gr.Textbox(label="Encrypted Features (Ciphertext)", interactive=False, lines=5)
254
 
255
  with gr.Accordion("Advanced Settings", open=False):
256
  rec_threshold = gr.Slider(-512*5, 512*5, value=133, label="Match Strictness", info="A higher value means a stricter match is required.")
 
262
  rec_result = gr.HTML()
263
 
264
  def secure_recognition_flow(ref_img, probe_img, threshold, sec_level):
265
+ # Reset UI
266
+ yield "Initializing...", "", gr.update(visible=False), None, None, gr.update(visible=False), None, None
267
+
268
+ # Process Reference Image
269
+ yield "Extracting reference features...", "", gr.update(visible=False), None, None, gr.update(visible=False), None, None
270
+ ref_emb, _ = extract_embedding(ref_img, "enroll")
271
+
272
+ yield "Encrypting reference features...", "", gr.update(visible=True), {"embedding": ref_emb}, None, gr.update(visible=False), None, None
273
  run_binary("./bin/encReference.bin", sec_level, "encrypt")
274
+ ref_ciphertext, _ = run_binary("./bin/encReference.bin", sec_level, "print")
275
+
276
+
277
+ # Process Probe Image
278
+ yield "✅ Reference Encrypted. Extracting probe features...", "", gr.update(visible=True), {"embedding": ref_emb}, ref_ciphertext, gr.update(visible=False), None, None
279
+ probe_emb, _ = extract_embedding(probe_img, "auth")
280
+
281
+ yield "Encrypting probe features...", "", gr.update(visible=True), {"embedding": ref_emb}, ref_ciphertext, gr.update(visible=True), {"embedding": probe_emb}, None
282
  run_binary("./bin/encProbe.bin", sec_level, "encrypt")
283
+ probe_ciphertext, _ = run_binary("./bin/encProbe.bin", sec_level, "print")
284
+
285
+ # Perform Match
286
+ yield "✅ Probe Encrypted. Performing Secure Match...", "", gr.update(visible=True), {"embedding": ref_emb}, ref_ciphertext, gr.update(visible=True), {"embedding": probe_emb}, probe_ciphertext
287
  run_binary("./bin/recDecision.bin", sec_level, "decision", str(threshold))
288
+
289
+ yield "✅ Match Computed. Decrypting Result...", "", gr.update(visible=True), {"embedding": ref_emb}, ref_ciphertext, gr.update(visible=True), {"embedding": probe_emb}, probe_ciphertext
290
  output, _ = run_binary("./bin/decDecision.bin", sec_level, "decision")
291
+
292
  if "match" in output.lower():
293
  result_html = """<div class="result-container match-verified"><h2>✅ MATCH VERIFIED</h2><p>Identity successfully confirmed under FHE.</p></div>"""
294
  else:
295
  result_html = """<div class="result-container no-match"><h2>❌ NO MATCH</h2><p>Identity verification failed.</p></div>"""
296
+ yield "Done!", result_html, gr.update(visible=True), {"embedding": ref_emb}, ref_ciphertext, gr.update(visible=True), {"embedding": probe_emb}, probe_ciphertext
297
 
298
  rec_run_btn.click(
299
  fn=secure_recognition_flow,
300
  inputs=[rec_ref_img, rec_probe_img, rec_threshold, rec_sec_level],
301
+ outputs=[rec_status, rec_result, rec_ref_features_group, rec_ref_raw_features, rec_ref_encrypted_features, rec_probe_features_group, rec_probe_raw_features, rec_probe_encrypted_features]
302
  )
303
 
304
  # --- 1:N Search Demo ---
 
314
 
315
  with gr.Row():
316
  with gr.Column():
317
+ gr.HTML('<h3 class="step-header">1. Enroll Subjects into DB</h3>')
318
+ search_enroll_img = create_image_selection_ui("Select Image to Enroll", EXAMPLE_IMAGES_ENROLL)
319
  search_enroll_btn = gr.Button("➕ Encrypt & Add to Database", variant="secondary")
320
+ with gr.Group(visible=False) as enroll_features_group:
321
+ enroll_raw_features = gr.JSON(label="Raw Features (Plaintext)")
322
+ enroll_encrypted_features = gr.Textbox(label="Encrypted Features (Ciphertext)", interactive=False, lines=5)
323
  search_enroll_status = gr.HTML()
324
+
325
  with gr.Column():
326
+ gr.HTML('<h3 class="step-header">2. Search for a Subject</h3>')
327
+ search_probe_img = create_image_selection_ui("Select Image to Search", EXAMPLE_IMAGES_AUTH)
328
  search_run_btn = gr.Button("🚀 Perform Secure 1:N Search", variant="primary", size="lg")
329
+ with gr.Group(visible=False) as search_features_group:
330
+ search_raw_features = gr.JSON(label="Raw Features (Plaintext)")
331
+ search_encrypted_features = gr.Textbox(label="Encrypted Features (Ciphertext)", interactive=False, lines=5)
332
  search_status = gr.HTML(elem_classes="status-text")
333
 
334
  search_result = gr.HTML()
 
337
  search_threshold = gr.Slider(-512*5, 512*5, value=133, label="Match Strictness")
338
  search_sec_level = gr.Dropdown(SECURITYLEVELS, value="128", label="Security Level")
339
 
340
+ def secure_enroll_flow(image, sec_level):
341
+ global DB_SUBJECT_COUNT
342
+ if image is None: raise gr.Error("Please provide an image to enroll.")
343
+
344
+ current_id = DB_SUBJECT_COUNT
345
+
346
+ yield "Extracting features...", gr.update(visible=False), None, None
347
+ embedding, emb_path = extract_embedding(image, "search_enroll")
348
+
349
+ yield "Encrypting features...", gr.update(visible=True), {"embedding": embedding}, None
350
+ run_binary("./bin/search.bin", sec_level, "encRef", emb_path, str(current_id))
351
+ ciphertext, _ = run_binary("./bin/search.bin", sec_level, "printRef")
352
+
353
+ yield "Adding to secure database...", gr.update(visible=True), {"embedding": embedding}, ciphertext
354
  run_binary("./bin/search.bin", sec_level, "addRef")
355
+
356
+ DB_SUBJECT_COUNT += 1
357
+ yield f"✅ Subject with ID {current_id} added. Total subjects: {DB_SUBJECT_COUNT}.", gr.update(visible=True), {"embedding": embedding}, ciphertext
358
 
359
  def secure_search_flow(image, threshold, sec_level):
360
  if image is None: raise gr.Error("Please provide an image to search.")
361
+
362
+ yield "Extracting probe features...", "", gr.update(visible=False), None, None
363
+ embedding, emb_path = extract_embedding(image, "search_auth")
364
+
365
+ yield "Encrypting probe features...", "", gr.update(visible=True), {"embedding": embedding}, None
366
  run_binary("./bin/search.bin", sec_level, "encProbe", emb_path)
367
+ ciphertext, _ = run_binary("./bin/search.bin", sec_level, "printProbe")
368
+
369
+ yield "✅ Probe encrypted. Searching database...", "", gr.update(visible=True), {"embedding": embedding}, ciphertext
370
  run_binary("./bin/search.bin", sec_level, "search")
371
+
372
+ yield "✅ Search complete. Decrypting results...", "", gr.update(visible=True), {"embedding": embedding}, ciphertext
373
  output, _ = run_binary("./bin/search.bin", sec_level, "decDecisionClear", str(threshold))
374
+
375
  if "found" in output.lower():
376
  result_html = """<div class="result-container match-verified"><h2>✅ SUBJECT FOUND</h2><p>The subject was successfully found in the database.</p></div>"""
377
  else:
378
  result_html = """<div class="result-container no-match"><h2>❌ NOT FOUND</h2><p>The subject was not found in the database.</p></div>"""
379
+ yield "Done!", result_html, gr.update(visible=True), {"embedding": embedding}, ciphertext
380
 
381
  search_enroll_btn.click(
382
  fn=secure_enroll_flow,
383
+ inputs=[search_enroll_img, search_sec_level],
384
+ outputs=[search_enroll_status, enroll_features_group, enroll_raw_features, enroll_encrypted_features]
385
  )
386
 
387
  search_run_btn.click(
388
  fn=secure_search_flow,
389
  inputs=[search_probe_img, search_threshold, search_sec_level],
390
+ outputs=[search_status, search_result, search_features_group, search_raw_features, search_encrypted_features]
391
  )
392
 
393
  # --- Launch the Application ---