Ian Goldberg ef2b926a0c Add MIT licence | пре 10 месеци | |
---|---|---|
docker | пре 11 месеци | |
repro | пре 10 месеци | |
.dockerignore | пре 11 месеци | |
.gitignore | пре 11 месеци | |
LICENSE | пре 10 месеци | |
Makefile | пре 1 година | |
README.md | пре 10 месеци | |
aes.hpp | пре 2 година | |
avl.cpp | пре 1 година | |
avl.hpp | пре 1 година | |
bitutils.hpp | пре 1 година | |
bst.cpp | пре 1 година | |
bst.hpp | пре 1 година | |
cdpf.cpp | пре 1 година | |
cdpf.hpp | пре 1 година | |
cdpf.tcc | пре 1 година | |
cell.cpp | пре 1 година | |
cell.hpp | пре 1 година | |
corotypes.hpp | пре 2 година | |
coroutine.hpp | пре 2 година | |
dpf.hpp | пре 1 година | |
duoram.cpp | пре 1 година | |
duoram.hpp | пре 1 година | |
duoram.tcc | пре 1 година | |
heap.cpp | пре 1 година | |
heap.hpp | пре 1 година | |
heapsampler.cpp | пре 1 година | |
heapsampler.hpp | пре 1 година | |
mpcio.cpp | пре 1 година | |
mpcio.hpp | пре 1 година | |
mpcio.tcc | пре 1 година | |
mpcops.cpp | пре 1 година | |
mpcops.hpp | пре 1 година | |
mpcops.tcc | пре 1 година | |
online.cpp | пре 1 година | |
online.hpp | пре 2 година | |
options.hpp | пре 1 година | |
prac.cpp | пре 1 година | |
preproc.cpp | пре 1 година | |
preproc.hpp | пре 2 година | |
prg.hpp | пре 1 година | |
rdpf.cpp | пре 1 година | |
rdpf.hpp | пре 1 година | |
rdpf.tcc | пре 1 година | |
shapes.hpp | пре 1 година | |
shapes.tcc | пре 1 година | |
types.hpp | пре 1 година |
Ian Goldberg, iang@uwaterloo.ca
Sajin Sasy, ssasy@uwaterloo.ca
Adithya Vadapalli, avadapalli@cse.iitk.ac.in
PRAC implements three-party secure computation, with a particular focus on computations that require random access to memory. Parties 0 and 1 are the computational peers, while party 2 is the server. The server aids the computation, but generally does much less than the two computational peers.
This work appeared in:
Sajin Sasy, Adithya Vadapalli, Ian Goldberg. "PRAC: Round-Efficient 3-Party MPC for Dynamic Data Structures". Proceedings on Privacy Enhancing Technologies 2024(3). https://eprint.iacr.org/2023/1897.
The reproduction instructions for the PoPETs paper are in the README file in the repro
directory of this (popets-repro
) branch.
The multi-party computation (MPC) makes use of resources, most notably multiplication triples and distributed point functions (DPFs). These resources can be precomputed; they are independent of the values in the computation being performed, so you only need to know how many of each you'll need.
PRAC has three modes:
Precomputation mode
Online mode
Online-only mode
PRAC supports two kinds of threading: communication threads and local processing threads.
Currently, all of the interesting multithreading (except for some unit tests) are local processing threads.
Build with make
. The build has been tested on Ubuntu 20.04 and Ubuntu
22.04. You'll need libbsd-dev and libboost-all-dev.
You'll need three terminals with the built binary, either on the same machine, or different machines. If it's on the same machine, it's OK for them all to be in the very same directory; the saved resources for the different parties won't clobber each other.
In each terminal, run ./prac opts player_num player_addresses args
player_num
is 0
, 1
, or 2
player_addresses
is:
For preprocessing mode:
opts
should be -p
to indicate preprocessing mode-a
to indicate that the resources being computed should be appended to existing resource files, rather than replacing them. This is useful if you want to create for example a large number of large DPFs. Each DPF creation consumes a lot of memory, and all the DPFs are computed simultaneously in order to save network round trips. To compute them in smaller batches if your memory is limited, run ./prac
several times, each with the -a
option.-e
option means to store precomputed DPFs in expanded form. This can take a lot of disk space for large DPFs, and depending on your disk speed and CPU capabilities and number of local processing threads, it can actually be faster to recompute the expansion than to read it from disk.-C num
option to enable num
communication threads. As above, this is probably not what you want.-t num
option to enable num
local processing threads.Then the args
specify what resources to compute. You actually only need to provide the args to player 2 (the server) in preprocessing mode; it will inform the other players what is being computed. The other players will ignore their arguments in preprocessing mode.
The args in preprocessing mode are each of the form type:num
to indicate to create num
resources of the given type. The available types include:
m
: a multiplication tripleh
: a multiplication half-triplea
: an AND triples
: a select triplerd
: A DPF of depth d
for random accesses to memory (RDPF). A DPF of depth d can be used to process 2d memory locations.
Can optionally take a suffix .w
(for example, r26.3
) where w
is an integer between 1 and 5 to indicate the width of the RDPF (the default is 1).id
: An Incremental DPF of depth d
for random accesses to memory (IDPF). Can take an optional width suffix as above.c
: a DPF for comparisons (CDPF)If you do have multiple communication threads, you can optionally specify different sets of resources to create in each one by prefixing communication thread i's list with Ti
(i starts at 0). If the args do not start with such an indication, each communication thread will use a copy of the provided list.
Example: In three terminals on the same host, run:
./prac -t 8 -p 0
./prac -t 8 -p 1 localhost
./prac -t 8 -p 2 localhost localhost m:100 r6:10 r20:5 c:50
to create 100 multiplication triples, 10 RDPFs of depth 6, 5 RDPFs of depth 20, and 50 CDPFs, using 8 local processing threads.
For online mode:
The useful options in online mode are:
-C num
specifies the number of communication threads to use.-t num
specifies the number of processing threads to use.-x
indicates that you wish to use an XOR-shared memory instead of the default additive-shared memory. Some computations can work with either type (and respect this option) while others cannot (and ignore this option).The args in online mode specify what computation to do. These are mostly unit tests and benchmarks. The interesting ones for now:
duoram depth items
: in a memory of size 2depth, do items dependent updates, items dependent reads, items independent reads, items independent updates, items dependent writes, and items dependent interleaved reads and writes. Each batch is timed and measured independently.read depth items
: similar, but only time dependent reads.bbsearch [-r] depth iters
: iters iterations of basic binary search on an array of size 2depth-1. The -r
flag means to generate (and sort, so it's more expensive) a random array rather than using a pre-sorted array.bsearch [-r] depth iters
: as above, but for our optimized binary search rather than the basic one.heap -m maxsize -d datasize -i numinserts -e numextracts -opt optflag -s sanityflag
: the heap benchmark. Allocate a heap of maximum size 2maxsize-1 elements, and initialize the first 2datasize elements of it. Perform numinserts insertions and numextracts extractions. Set optflag to 1 to use the optimized heap algorithms, or 0 otherwise. Set sanityflag to 1 to check the results after each operation, or 0 otherwise.avl -m size -i numinserts -e numextracts -opt optflag -s sanityflag
: the AVL benchmark. Initialize an AVL tree with 2size elements. Insert numinseerts more elements, and delete numextracts elements. Set optflag to 1 to use the optimized AVL algorithms, or 0 otherwise. Set sanityflag to 1 to check the results after each operation, or 0 otherwise.avl_tests
: unit tests for the AVL algorithmsheapsampler n k
: the heap-based oblivious stream sampler benchmark. Obliviously select a random subset of k elements from a stream arriving one element at a time, using O(k) memory. Stop after n elements.It is vital that all three players are told the same computation to run!
The output of online mode (for each player) includes timings (real and CPU time), the number of messages sent, the number of message bytes sent in total, the Lamport clock (the number of network latencies experienced), and the number of local AES operations performed (each AES operation is an encryption of a single block), as well as the list of the number of precomputed resources used in each communication thread.
Example: In three terminals on the same host, run:
./prac -t 8 -p 0
./prac -t 8 -p 1 localhost
./prac -t 8 -p 2 localhost localhost r20:90
to complete the preprocessing required for the following computation, using 8 threads, and then:
./prac -t 8 0 duoram 20 10
./prac -t 8 1 localhost duoram 20 10
./prac -t 8 2 localhost localhost duoram 20 10
to do the online portion of the computation, also using 8 local processing threads.
For online-only mode:
The options and arguments are the same as for online mode, only you also add the -o
option, and you don't have to have run preprocessing mode first. At the end of the run, PRAC will output the number of resources of each type created, in a format suitable for passing as the arguments to preprocessing mode.
Example: In three terminals on the same host, run:
./prac -o -t 8 0 duoram 20 10
./prac -o -t 8 1 localhost duoram 20 10
./prac -o -t 8 2 localhost localhost duoram 20 10
No separate preprocessing step is needed.
cd docker
./build-docker
./start-docker
Then to simulate network latency and capacity (optional):
./set-networking 30ms 100mbit
To turn that off again:
./unset-networking
If you have a NUMA machine, you might want to pin each player to one
NUMA node. To do that, set these environment variables before running
./run-experiment
below:
export PRAC_NUMA_P0="numactl -N 1 -m 1"
export PRAC_NUMA_P1="numactl -N 2 -m 2"
export PRAC_NUMA_P2="numactl -N 3 -m 3"
Adjust the numactl arguments to taste, of course, depending on your
machine's configuration. Alternately, you can use things like -C 0-7
instead of -N 1
to pin to specific cores, even on a non-NUMA machine.
Run experiments:
./run-experiment opts args
./prac
above, not including the
player number and other players' addresses, which are filled in
automatically. The number of processing threads for each player
is also automatically set to the number of cores available in the
given PRAC_NUMA_P{0,1,2}
configuration.When you're all done:
./stop-docker