7 releases
0.6.0 | Jul 30, 2024 |
---|---|
0.5.0 | Jun 28, 2024 |
0.4.4 | Jun 19, 2024 |
0.4.3 | Apr 10, 2024 |
0.4.1 | Jan 28, 2024 |
#256 in Cryptography
25 downloads per month
63KB
1K
SLoC
fss
Function secret sharing including distributed comparison & point functions
Get Started
First add the crate as a dependency:
# Run in your project directory
cargo add fss-rs
By default the PRG implementations and multi-threading are included. You can disable the default feature to select by yourself. If you are on ARM machines, see the Performance section for hardware acceleration.
Then construct a PRG implementing the corresponding Prg
trait, and construct an impl DcfImpl
or DpfImpl
to use the PRG.
Check the doc comment for the meanings of the generic parameters.
If you want to set the bit length of the domain (input domain, instead of the range that is the output domain), check new_with_filter
method.
use rand::prelude::*;
// Matyas-Meyer-Oseas (via AES128) provides 128-bit security and should be enough.
// Hirose (via AES256) still only provides 128-bit security because the output is not chained.
// But Hirose can be helpful is you are forced to choose AES256.
use fss_rs::prg::Aes128MatyasMeyerOseasPrg;
use fss_rs::dcf::{Dcf, DcfImpl};
let keys: [[u8; 16]; 4] = thread_rng().gen();
let prg = Aes128MatyasMeyerOseasPrg::<16, 2, 4>::new(std::array::from_fn(|i| &keys[i]));
// DCF for example
let dcf = DcfImpl::<16, 16, _>::new(prg);
Finally, for key generation, construct the function to be shared together with 2 init keys, and call gen
:
use fss_rs::dcf::{BoundState, CmpFn};
use fss_rs::group::byte::ByteGroup;
use fss_rs::group::Group;
let s0s: [[u8; 16]; 2] = thread_rng().gen();
let f = CmpFn {
alpha: thread_rng().gen(),
// `ByteGroup` for example
beta: ByteGroup(thread_rng().gen()),
bound: BoundState::LtBeta,
};
let keys = dcf.gen(&f, [&s0s[0], &s0s[1]]);
See the doc comment of the returned Share
for how to split it into 2 shares.
The 2 shares are combined like this because they share many fields.
And for evaluation, construct the evaluated points, reverse the output buffer, and call eval
:
let x: [u8; 16] = thread_rng().gen();
let mut y = ByteGroup::zero();
// The 2 parties use `true` / `false` to evaluate independently
dcf.eval(false, &k, &[&x], &mut [&mut y]);
For full domain evaluation, use full_eval
instead.
While similar to eval
, full_eval
does not accept a vector of x
, and instead expects a vector of y
whose length is 2 ** (IN_BLEN * 8)
to store all evaluated y
.
More examples are available as benchmarks in the benches dir
References
- DCF: Elette Boyle, Nishanth Chandran, Niv Gilboa, Divya Gupta, Yuval Ishai, Nishant Kumar, and Mayank Rathee. "Function Secret Sharing for Mixed-Mode and Fixed-Point Secure Computation." In EUROCRYPT. 2021.
- DPF: Elette Boyle, Niv Gilboa, and Yuval Ishai. "Function Secret Sharing: Improvements and Extensions." In CCS. 2016.
- Fast PRG: Leo de Castro and Anitgoni Polychroniadou. "Lightweight, Maliciously Secure Verifiable Function Secret Sharing." In EUROCRYPT. 2022.
- Fast PRG: Frank Wang, Catherine Yun, Shafi Goldwasser, Vinod Vaikuntanathan, and Matei Zaharia. "Splinter: Practical Private Queries on Public Data." In NDSI. 2017.
Performance
The hot path of the project is PRG and XOR operations. We use the aes crate of RustCrypto for PRG. For XOR operations, We use Rust std SIMD for nightly Rust, or the wide crate that has 9M all-time downloads for stable Rust.
For PRG, enabling archtecture-specified CPU intrinsics can largely boost the performance. The aes crate by default performs runtime detection of CPU intrinsics and uses them if available.
For x86/x86_64 (i686
/x86_64
in targets), AES-NI is used if available, which works out-of-the-box.
For ARMv8 (aarch64
in targets), while ARMv8 Cryptography Extensions is supported, to use it,
in addition to the above, you need to set some flags to enable it.
See the doc of the aes crate for details.
We also quote the section here:
From https://docs.rs/aes/0.8.3/aes/#armv8-intrinsics-rust-161
ARMv8 intrinsics (Rust 1.61+)
On
aarch64
targets includingaarch64-apple-darwin
(Apple M1) and Linux targets such asaarch64-unknown-linux-gnu
andaarch64-unknown-linux-musl
, support for using AES intrinsics provided by the ARMv8 Cryptography Extensions is available when using Rust 1.61 or above, and can be enabled using theaes_armv8
configuration flag.On Linux and macOS, when the
aes_armv8
flag is enabled support for AES intrinsics is autodetected at runtime. On other platforms theaes
target feature must be enabled via RUSTFLAGS.
Benchmark
We use Criterion.rs for benchmarking.
Criterion.rs reports criterion.tar.zst
are included in releases.
We use a (my) laptop as the benchmarking machine. It is charged with the power plugged in when benchmarking. Its CPU is AMD Ryzen 7 5800H, which is 8C16T. We use rayon as the data-parallelism library, which establishes 16 threads when benchmarking with multithreading. We ensure its memory is enough for benchmarking. Notice that we do not close other programs as many as possible to reduce scheduling, though all GUI applications except VSCode are closed and we do avoid doing any other things at the same time.
Changelog
Correctness fixes:
fss_rs::group::int_prime
impl is corrected at v0.6.0.fss_rs::dcf::prg::Aes256HirosePrg
impl is corrected at v0.4.3 of the crate fss-rs, v0.5.2 and v0.6.3 of the crate dcf, and v0.5.2 of the crate dpf-fss (since it depends on the crate dcf).
See CHANGELOG.md for the full changelog.
License
Copyright (C) 2023 Yulong Ming (myl7)
SPDX-License-Identifier: Apache-2.0
Dependencies
~0.9–1.5MB
~36K SLoC