
Reference implementation of privacy-preserving face recognition using replicated secret sharing in MP-SPDZ, with quantized GhostFaceNet inference, benchmarks, and QAT tooling.
Official implementation of GhostFaceMPC: Privacy-Preserving Face Recognition with Multi-Party Computation (Davide Carnemolla, Dario Catalano, Mario Di Raimondo — University of Catania). Paper: Cryptology ePrint Archive, Paper 2026/2499.
GhostFaceMPC runs face recognition with GhostFaceNetV1 (width 1.3, stride 1, ArcFace head, trained on MS1MV3) among three servers with replicated secret sharing in MP-SPDZ.
replicated-ring-party) and
malicious with abort (ps-rep-ring-party).This repository contains exactly the code needed to reproduce the experiments of the paper.
@misc{cryptoeprint:2026/2499,
author = {Davide Carnemolla and Dario Catalano and Mario Di Raimondo},
title = {{GhostFaceMPC}: Privacy-Preserving Face Recognition with Multi-Party Computation},
howpublished = {Cryptology {ePrint} Archive, Paper 2026/2499},
year = {2026},
url = {https://eprint.iacr.org/2026/2499}
}
| Path | What it is |
|---|---|
src/ghostmpc/ | Python package and ghostmpc command line |
src/ghostmpc/codegen/ | compiler from the model manifest to an MP-SPDZ program |
src/ghostmpc/eval/ | clear-text ring oracle (bit-exact with the MPC program) and accuracy evaluation |
src/ghostmpc/benchmark/ | three-party benchmark harness and emulated networks |
src/ghostmpc/training/ | quantization-aware training on the ring-faithful forward pass |
third_party/patches/ | the virtual-machine instructions this work adds to MP-SPDZ |
baselines/ | the baselines: TensorFlow plaintext, naive MP-SPDZ, EzPC/Porthos |
run_experiments.sh | one script that runs every experiment of the paper |
scripts/ | setup, rootless network emulation, table collection |
tests/ | unit tests (pytest) |
Machine. Linux on x86-64. The paper used a 32-core VM (Intel Xeon Gold 6238R) and runs 8 threads per party. All three servers run on one host.
Python. Python ≥ 3.10 (tested with 3.11).
MP-SPDZ build dependencies (upstream list):
sudo apt-get install automake build-essential clang cmake git libboost-dev \
libboost-filesystem-dev libboost-iostreams-dev libboost-thread-dev \
libgmp-dev libntl-dev libsodium-dev libssl-dev libtool python3 python3-venv
LAN/WAN emulation. Needs iproute2 (ip, tc), iputils-ping,
unshare (util-linux) and unprivileged user namespaces. The script needs no
root. On Debian/Ubuntu: sudo sysctl kernel.unprivileged_userns_clone=1.
Porthos baseline only.
libboost-system-devopam install ocamlbuild menhir ocamlfind stdintgit clone --recursive https://github.com/crypto-unict/ghostfacempc.git
cd ghostfacempc
scripts/setup.sh
scripts/setup.sh does four things:
.venv and installs the package. This pulls tensorflow-cpu,
Pillow, onnx, onnxruntime and onnxsim.third_party/MP-SPDZ:
third_party/patches/;MY_CFLAGS += -DRING_SIZE=32 in CONFIG.mine);replicated-ring-party.x and ps-rep-ring-party.x;The model files land in artifacts/:
| File | Content |
|---|---|
GhostFaceNet_W1.3_S1_ArcFace.h5 | float teacher, from the GhostFaceNets release |
model/ | the quantized ring32/f6/f_w9 model, with its accuracy reports |
model-ring64-f16-b0/ | ring64 manifest the Porthos baseline is exported from |
legacy-scalar-236/ | ring64/f20 manifest of the naive MP-SPDZ baseline |
The bundles are release assets of this repository, and every archive is
checked against its SHA-256. ghostmpc fetch-bundles --bundle qat-start also
downloads the manifest QAT starts from (see §5).
The accuracy experiment and the plaintext baseline read five InsightFace
evaluation sets: LFW, AgeDB-30, CALFW, CPLFW and CFP-FP. Use the .bin files
distributed with the MS1MV3 training data of the
InsightFace dataset zoo
and place them as:
datasets/benchmarks/{lfw,agedb_30,calfw,cplfw,cfp_fp}.bin
scripts/setup.sh verifies them against the SHA-256 digests we used. The MPC
benchmarks do not need the datasets: their communication does not depend on
the input values, so they secret-share synthetic inputs.
./run_experiments.sh --quick verification # smoke test, about one hour
./run_experiments.sh all # every table of the paper
./run_experiments.sh tables # print the tables measured so far
Results go to results/ (one report.json and summary.csv per run), and
tables writes results/tables.md in the layout of the paper. Targets can be
run separately and in any order. A run whose report already exists is skipped.
| Target | Paper | Runtime on our machine (approx.) |
|---|---|---|
accuracy | comparison table, accuracy columns | 3 h per dataset per core; split with WORKERS |
verification | Face Verification Benchmarks: HbC and M, Co-Host / LAN / Fast-WAN / WAN | ~6 h |
identification | Face Identification Benchmarks: 1:128 closed set, same grid | ~6 h |
plaintext | comparison table, TensorFlow row | 1 min |
naive | comparison table, MP-SPDZ (naive) row | ~1 h including compilation |
porthos | comparison table, EzPC (Porthos) row | ~5 min build + ~1.5 h |
baselines | the three baselines | |
ablation | ablation table: the optimizations one at a time, from the naive baseline to GhostFaceMPC (HbC, co-host) | ~4 h |
Environment variables:
| Variable | Meaning | Default |
|---|---|---|
THREADS | threads per party | 8 |
NETWORKS | networks to measure | co-host lan fast-wan wan |
WORKERS | processes for the accuracy oracle | number of CPUs |
POOLS, WARMUPS, TRIALS | override the pool design | the paper's |
RESULTS | output directory | results |
--quick runs one pool of one warm-up and one measured request, and the
accuracy on the first 600 pairs of each dataset.