Vishnu Naresh Boddeti
commited on
Commit
·
f5a949f
1
Parent(s):
06a7ef6
minor updates
Browse files
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
| 217 |
run_binary("./bin/encReference.bin", sec_level, "encrypt")
|
| 218 |
-
|
| 219 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
run_binary("./bin/encProbe.bin", sec_level, "encrypt")
|
| 221 |
-
|
|
|
|
|
|
|
|
|
|
| 222 |
run_binary("./bin/recDecision.bin", sec_level, "decision", str(threshold))
|
| 223 |
-
|
|
|
|
| 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 |
-
|
| 251 |
-
|
| 252 |
search_enroll_btn = gr.Button("➕ Encrypt & Add to Database", variant="secondary")
|
|
|
|
|
|
|
|
|
|
| 253 |
search_enroll_status = gr.HTML()
|
|
|
|
| 254 |
with gr.Column():
|
| 255 |
-
|
|
|
|
| 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 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
run_binary("./bin/search.bin", sec_level, "addRef")
|
| 273 |
-
|
|
|
|
|
|
|
| 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 |
-
|
| 278 |
-
|
|
|
|
|
|
|
|
|
|
| 279 |
run_binary("./bin/search.bin", sec_level, "encProbe", emb_path)
|
| 280 |
-
|
|
|
|
|
|
|
| 281 |
run_binary("./bin/search.bin", sec_level, "search")
|
| 282 |
-
|
|
|
|
| 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,
|
| 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 ---
|