This is the end-to-end implementation of the USENIX Security '25 paper "FABLE: Batched Evaluation on Confidential Lookup Tables in 2PC."
The extended version of FABLE's paper can be found at https://eprint.iacr.org/2025/1081. You may also find the artifact evaluation at FABLE-AE (https://github.com/cmu-cryptosystems/FABLE-AE).
The code contains the following components:
src: The source code of FABLE.src/GC: FABLE's subprotocols' implementation.src/OT: Our re-implementation of the SPLUT+ baseline.src/utils: Timing utilities.src/bench_fable.cpp: The benchmarking script for FABLE.src/bench_splut.cpp: The benchmarking script for SPLUT+.
test: The unit tests for FABLE and some other baselines.extern: The external libraries.cmake: Patches to apply to the external libraries..github: The GitHub CI workflow to automatically build the code and run a smoke test.
We recommend setting up the environment with Docker. To do this, build a Docker image using the Dockerfile, which will install all dependencies and build FABLE in /workspace/FABLE.
It is also possible to install the dependencies with conda.
mamba create -n fable gcc gxx cmake=3.31 make ninja fmt mpfr openmp openssl clang clangxx boost pkg-config -c conda-forgeWe use CMake to build the project.
First, please update the submodules if you have not already done so:
git submodule update --init --recursiveTo configure, use
cmake -S . -B buildSupported options include
-
LUT_INPUT_SIZE: The input bits$\delta$ of the LUT. Default: 20. -
LUT_OUTPUT_SIZE: The output bits$\sigma$ of the LUT. Default: 20. -
LUT_MAX_LOG_SIZE: The binary logarithm of the LUT size, rounded up to the nearest integer. Default: same asLUT_INPUT_SIZE. For example, to build a FABLE protocol for a LUT with 24 input bits, 64 output bits, and$2^{20}$ rows, the project can be configured by
cmake -S . -B build -DLUT_INPUT_SIZE=24 -DLUT_OUTPUT_SIZE=64 -DLUT_MAX_LOG_SIZE=20 To build the executable, use
cmake --build ./build --target fable --parallelwhich will generate an executable ./build/bin/fable.
To test ./build/bin/fable, launch the following commands in two separate terminals.
./build/bin/fable $NETWORK_HOST r=1 $optional_args
./build/bin/fable $NETWORK_HOST r=2 $optional_args$NETWORK_HOST is the IP address of ALICE (the terminal that is running with r=1). If the terminals are on the same machine, then $NETWORK_HOST can be set as 127.0.0.1.
$optional_args contains the following options:
p: The port number for communication. Default: 8000.bs: The batch size of the input. Default: 4096.db: The LUT size. Default:exp2(LUT_INPUT_SIZE).seed: The random seed. Default: 12345.par: Whether to enable parallelization. Default: 1.thr: Number of threads used in parallelization. Default: 16.l: Type of the LUT. Default: 0.- 0 = Random LUT.
- 1 = Gamma Function.
- 2 = Cauchy Distance.
- 3 = LUT filled with ones.
h: The OPRF type. Default: 0.- 0 = LowMC
- 1 = AES
f: Whether to do operator fusion to save communication rounds. Default: 0.
If you would like to use our implementation of FABLE, consider citing our paper:
@InProceedings{su2025fable,
author = {Zhengyuan Su and Qi Pang and Simon Beyzerov and Wenting Zheng},
editor = {Lujo Bauer and Giancarlo Pellegrino},
title = {{FABLE:} Batched Evaluation on Confidential Lookup Tables in 2PC},
booktitle = {34th {USENIX} Security Symposium, {USENIX} Security 2025, Seattle, WA, USA, August 13-15, 2025},
pages = {1945--1964},
publisher = {{USENIX} Association},
year = {2025},
url = {https://www.usenix.org/conference/usenixsecurity25/presentation/su-zhengyuan}
}