use std::hint::black_box;
use std::sync::OnceLock;
use std::time::Instant;
use secret_sharing::{
asmuth_bloom, benaloh_leichter as bl, blakley, blakley_meadows, brickell, bytes, cgma_vss,
csprng::{Csprng, OsRng},
decode::reconstruct_with_errors,
field::{mersenne127, PrimeField},
ida, ito, karchmer_wigderson as kw, kgh, kothari, massey, mignotte, proactive, ramp, shamir,
trivial, visual, vss, yamamoto, BigUint, ChaCha20Rng,
};
const K: usize = 3;
const N: usize = 5;
fn ms_per_op(elapsed: std::time::Duration, n: usize) -> f64 {
elapsed.as_secs_f64() * 1000.0 / n as f64
}
fn iters(base: usize) -> usize {
static SCALE_PERCENT: OnceLock<usize> = OnceLock::new();
let scale = *SCALE_PERCENT.get_or_init(|| {
std::env::var("PILOT_SS_ITERS_PERCENT")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.map(|v| v.clamp(1, 100))
.unwrap_or(25)
});
base.saturating_mul(scale).div_ceil(100).max(1)
}
fn rng() -> ChaCha20Rng {
let mut os = OsRng::new().expect("/dev/urandom");
ChaCha20Rng::from_os_entropy(&mut os)
}
fn field() -> PrimeField {
PrimeField::new_unchecked(mersenne127())
}
const SECRET_BYTES: usize = 4096;
const CHUNK_BYTES: usize = 15;
fn chunks_4kb(rng: &mut ChaCha20Rng) -> Vec<BigUint> {
let mut bytes = vec![0u8; SECRET_BYTES];
rng.fill_bytes(&mut bytes);
let n_chunks = SECRET_BYTES.div_ceil(CHUNK_BYTES);
(0..n_chunks)
.map(|i| {
let start = i * CHUNK_BYTES;
let end = (start + CHUNK_BYTES).min(SECRET_BYTES);
BigUint::from_be_bytes(&bytes[start..end])
})
.collect()
}
fn build_large_mignotte_3_of_5() -> mignotte::MignotteSequence {
use secret_sharing::primes::{is_probable_prime, random_below};
let mut rng = ChaCha20Rng::from_seed(&[0xA1u8; 32]);
let mut lo = BigUint::one();
lo.shl_bits(130);
let mut span = BigUint::one();
span.shl_bits(130);
let mut found: Vec<BigUint> = Vec::new();
while found.len() < 5 {
let mut candidate = random_below(&mut rng, &span).expect("span > 0");
candidate = candidate.add_ref(&lo);
if !candidate.is_odd() {
continue;
}
if is_probable_prime(&candidate) && !found.contains(&candidate) {
found.push(candidate);
}
}
found.sort();
mignotte::MignotteSequence::new(found, 3).expect("valid 130-bit sequence")
}
fn shamir_split_kn(k: usize, n: usize) -> f64 {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(shamir::split(&f, &mut r, &s, k, n));
}
ms_per_op(t0.elapsed(), n_iter)
}
fn shamir_reconstruct_kn(k: usize, n: usize) -> f64 {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = shamir::split(&f, &mut r, &s, k, n);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(shamir::reconstruct(&f, &shares[..k], k).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
fn shamir_cold_split() -> f64 {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let t0 = Instant::now();
let shares = shamir::split(&f, &mut r, &s, K, N);
let elapsed = t0.elapsed();
black_box(shares);
ms_per_op(elapsed, 1)
}
fn shamir_cold_reconstruct() -> f64 {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = shamir::split(&f, &mut r, &s, K, N);
let t0 = Instant::now();
let recovered = shamir::reconstruct(&f, &shares[..K], K).unwrap();
let elapsed = t0.elapsed();
black_box(recovered);
ms_per_op(elapsed, 1)
}
fn blakley_cold_split() -> f64 {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let t0 = Instant::now();
let shares = blakley::split(&f, &mut r, &s, K, N);
let elapsed = t0.elapsed();
black_box(shares);
ms_per_op(elapsed, 1)
}
fn blakley_cold_reconstruct() -> f64 {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = blakley::split(&f, &mut r, &s, K, N);
let t0 = Instant::now();
let recovered = blakley::reconstruct(&f, &shares[..K], K).unwrap();
let elapsed = t0.elapsed();
black_box(recovered);
ms_per_op(elapsed, 1)
}
fn massey_cold_split() -> f64 {
let f = field();
let mut g = vec![vec![BigUint::one(); N + 1], vec![BigUint::zero(); N + 1]];
#[allow(clippy::needless_range_loop)]
for j in 1..=N {
g[1][j] = BigUint::from_u64(j as u64);
}
let scheme = massey::CodeScheme::new(f.clone(), g);
let mut r = rng();
let s = f.random(&mut r);
let t0 = Instant::now();
let shares = massey::split(&scheme, &mut r, &s);
let elapsed = t0.elapsed();
black_box(shares);
ms_per_op(elapsed, 1)
}
fn massey_cold_reconstruct() -> f64 {
let f = field();
let mut g = vec![vec![BigUint::one(); N + 1], vec![BigUint::zero(); N + 1]];
#[allow(clippy::needless_range_loop)]
for j in 1..=N {
g[1][j] = BigUint::from_u64(j as u64);
}
let scheme = massey::CodeScheme::new(f.clone(), g);
let mut r = rng();
let s = f.random(&mut r);
let shares = massey::split(&scheme, &mut r, &s);
let coalition: Vec<_> = shares.iter().take(2).cloned().collect();
let t0 = Instant::now();
let recovered = massey::reconstruct(&scheme, &coalition).unwrap();
let elapsed = t0.elapsed();
black_box(recovered);
ms_per_op(elapsed, 1)
}
fn main() {
let op = std::env::args().nth(1).unwrap_or_else(|| {
eprintln!("usage: pilot_ss <operation>");
std::process::exit(1);
});
let ms: f64 = match op.as_str() {
"shamir_split" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(shamir::split(&f, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"shamir_reconstruct" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = shamir::split(&f, &mut r, &s, K, N);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(shamir::reconstruct(&f, &shares[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"blakley_split" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(blakley::split(&f, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"blakley_reconstruct" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = blakley::split(&f, &mut r, &s, K, N);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(blakley::reconstruct(&f, &shares[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"kothari_split" => {
let scheme = kothari::vandermonde(field(), K, N);
let mut r = rng();
let s = scheme.field().random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(kothari::split(&scheme, &mut r, &s));
}
ms_per_op(t0.elapsed(), n_iter)
}
"kothari_reconstruct" => {
let scheme = kothari::vandermonde(field(), K, N);
let mut r = rng();
let s = scheme.field().random(&mut r);
let shares = kothari::split(&scheme, &mut r, &s);
let pairs: Vec<(usize, BigUint)> = (0..K).map(|c| (c, shares[c].clone())).collect();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(kothari::reconstruct(&scheme, &pairs).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"karchmer_wigderson_split" => {
let prog = kw::threshold_msp(field(), K, N);
let mut r = rng();
let s = prog.field().random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(kw::split(&prog, &mut r, &s));
}
ms_per_op(t0.elapsed(), n_iter)
}
"karchmer_wigderson_reconstruct" => {
let prog = kw::threshold_msp(field(), K, N);
let mut r = rng();
let s = prog.field().random(&mut r);
let shares = kw::split(&prog, &mut r, &s);
let coalition: Vec<_> = shares.iter().take(K).cloned().collect();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(kw::reconstruct(&prog, &coalition).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"brickell_split" => {
let f = field();
let vectors: Vec<Vec<BigUint>> = (1..=N)
.map(|j| {
let mut row = Vec::with_capacity(K);
let mut pow = BigUint::one();
let j_val = BigUint::from_u64(j as u64);
for _ in 0..K {
row.push(pow.clone());
pow = f.mul(&pow, &j_val);
}
row
})
.collect();
let scheme = brickell::Scheme::new(f.clone(), vectors);
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(brickell::split(&scheme, &mut r, &s));
}
ms_per_op(t0.elapsed(), n_iter)
}
"brickell_reconstruct" => {
let f = field();
let vectors: Vec<Vec<BigUint>> = (1..=N)
.map(|j| {
let mut row = Vec::with_capacity(K);
let mut pow = BigUint::one();
let j_val = BigUint::from_u64(j as u64);
for _ in 0..K {
row.push(pow.clone());
pow = f.mul(&pow, &j_val);
}
row
})
.collect();
let scheme = brickell::Scheme::new(f.clone(), vectors);
let mut r = rng();
let s = f.random(&mut r);
let shares = brickell::split(&scheme, &mut r, &s);
let coalition: Vec<_> = shares.iter().take(K).cloned().collect();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(brickell::reconstruct(&scheme, &coalition).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"massey_split" => {
let f = field();
let mut g = vec![vec![BigUint::one(); N + 1], vec![BigUint::zero(); N + 1]];
#[allow(clippy::needless_range_loop)]
for j in 1..=N {
g[1][j] = BigUint::from_u64(j as u64);
}
let scheme = massey::CodeScheme::new(f.clone(), g);
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(massey::split(&scheme, &mut r, &s));
}
ms_per_op(t0.elapsed(), n_iter)
}
"massey_reconstruct" => {
let f = field();
let mut g = vec![vec![BigUint::one(); N + 1], vec![BigUint::zero(); N + 1]];
#[allow(clippy::needless_range_loop)]
for j in 1..=N {
g[1][j] = BigUint::from_u64(j as u64);
}
let scheme = massey::CodeScheme::new(f.clone(), g);
let mut r = rng();
let s = f.random(&mut r);
let shares = massey::split(&scheme, &mut r, &s);
let coalition: Vec<_> = shares.iter().take(2).cloned().collect();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(massey::reconstruct(&scheme, &coalition).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"ramp_split" => {
let f = field();
let mut r = rng();
let s: Vec<BigUint> = (0..K).map(|_| f.random(&mut r)).collect();
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(ramp::split(&f, &s, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"ramp_reconstruct" => {
let f = field();
let mut r = rng();
let s: Vec<BigUint> = (0..K).map(|_| f.random(&mut r)).collect();
let shares = ramp::split(&f, &s, N);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(ramp::reconstruct(&f, &shares[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"yamamoto_split" => {
let f = field();
let mut r = rng();
let s: Vec<BigUint> = (0..K).map(|_| f.random(&mut r)).collect();
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(yamamoto::split(&f, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"yamamoto_reconstruct" => {
let f = field();
let mut r = rng();
let s: Vec<BigUint> = (0..K).map(|_| f.random(&mut r)).collect();
let shares = yamamoto::split(&f, &mut r, &s, K, N);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(yamamoto::reconstruct(&f, &shares[..K], K, K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"blakley_meadows_split" => {
let f = field();
let mut r = rng();
let l = K - 1;
let s: Vec<BigUint> = (0..l).map(|_| f.random(&mut r)).collect();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(blakley_meadows::split(&f, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"blakley_meadows_reconstruct" => {
let f = field();
let mut r = rng();
let l = K - 1;
let s: Vec<BigUint> = (0..l).map(|_| f.random(&mut r)).collect();
let shares = blakley_meadows::split(&f, &mut r, &s, K, N);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(blakley_meadows::reconstruct(&f, &shares[..K], K, l).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"kgh_split" => {
let f = field();
let mut r = rng();
let s: Vec<BigUint> = (0..K).map(|_| f.random(&mut r)).collect();
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(kgh::split(&f, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"kgh_reconstruct" => {
let f = field();
let mut r = rng();
let s: Vec<BigUint> = (0..K).map(|_| f.random(&mut r)).collect();
let shares = kgh::split(&f, &mut r, &s, K, N);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(kgh::reconstruct(&f, &shares[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"vss_split" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(vss::deal(&f, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"vss_reconstruct" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = vss::deal(&f, &mut r, &s, K, N);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(vss::reconstruct(&f, &shares[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"cgma_vss_split" => {
let group = cgma_vss::rfc5114_modp_2048_256();
let mut r = rng();
let s = BigUint::from_u64(0x1234_5678_9abc_def0); let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(cgma_vss::deal(&group, &mut r, &s, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"cgma_vss_reconstruct" => {
let group = cgma_vss::rfc5114_modp_2048_256();
let mut r = rng();
let s = BigUint::from_u64(0x1234_5678_9abc_def0);
let (shares, commits) = cgma_vss::deal(&group, &mut r, &s, K, N);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for sh in &shares {
black_box(cgma_vss::verify_share(&group, &commits, sh));
}
black_box(cgma_vss::reconstruct(&group, &shares[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"mignotte_split" => {
let seq = mignotte::small_example_3_of_5();
let s = seq.alpha().add_ref(&BigUint::from_u64(1));
let n_iter = iters(5000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(mignotte::split(&seq, &s));
}
ms_per_op(t0.elapsed(), n_iter)
}
"mignotte_reconstruct" => {
let seq = mignotte::small_example_3_of_5();
let s = seq.alpha().add_ref(&BigUint::from_u64(1));
let shares = mignotte::split(&seq, &s);
let n_iter = iters(5000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(mignotte::reconstruct(&seq, &shares[..K]).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"mignotte_reconstruct_large" => {
let seq = build_large_mignotte_3_of_5();
let s = seq.alpha().add_ref(&BigUint::from_u64(1));
let shares = mignotte::split(&seq, &s);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(mignotte::reconstruct(&seq, &shares[..K]).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"asmuth_bloom_split" => {
let params = asmuth_bloom::small_example_3_of_5();
let mut r = rng();
let s = BigUint::from_u64(1);
let n_iter = iters(5000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(asmuth_bloom::split(¶ms, &mut r, &s));
}
ms_per_op(t0.elapsed(), n_iter)
}
"asmuth_bloom_reconstruct" => {
let params = asmuth_bloom::small_example_3_of_5();
let mut r = rng();
let s = BigUint::from_u64(1);
let shares = asmuth_bloom::split(¶ms, &mut r, &s);
let n_iter = iters(5000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(asmuth_bloom::reconstruct(¶ms, &shares[..K]).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"trivial_split" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(10_000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(trivial::split(&f, &mut r, &s, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"trivial_reconstruct" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = trivial::split(&f, &mut r, &s, N);
let n_iter = iters(20_000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(trivial::reconstruct(&f, &shares));
}
ms_per_op(t0.elapsed(), n_iter)
}
"ito_split" => {
let f = field();
let structure = ito::threshold_access_structure(N, K);
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(5000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(ito::split(&f, &mut r, &s, &structure));
}
ms_per_op(t0.elapsed(), n_iter)
}
"ito_reconstruct" => {
let f = field();
let structure = ito::threshold_access_structure(N, K);
let mut r = rng();
let s = f.random(&mut r);
let shares = ito::split(&f, &mut r, &s, &structure);
let coalition: Vec<_> = shares.iter().take(K).cloned().collect();
let n_iter = iters(10_000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(ito::reconstruct(&f, &structure, &coalition).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"benaloh_leichter_split" => {
let f = field();
let formula = bl::Formula::or(vec![
bl::Formula::and(vec![bl::Formula::party(1), bl::Formula::party(2)]),
bl::Formula::and(vec![bl::Formula::party(1), bl::Formula::party(3)]),
bl::Formula::and(vec![bl::Formula::party(2), bl::Formula::party(3)]),
]);
let mut r = rng();
let s = f.random(&mut r);
let n_iter = iters(20_000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(bl::split(&f, &mut r, &s, &formula));
}
ms_per_op(t0.elapsed(), n_iter)
}
"benaloh_leichter_reconstruct" => {
let f = field();
let formula = bl::Formula::or(vec![
bl::Formula::and(vec![bl::Formula::party(1), bl::Formula::party(2)]),
bl::Formula::and(vec![bl::Formula::party(1), bl::Formula::party(3)]),
bl::Formula::and(vec![bl::Formula::party(2), bl::Formula::party(3)]),
]);
let mut r = rng();
let s = f.random(&mut r);
let shares = bl::split(&f, &mut r, &s, &formula);
let pair: Vec<_> = shares.iter().take(2).cloned().collect();
let n_iter = iters(20_000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(bl::reconstruct(&f, &formula, &pair).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"proactive_refresh" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = shamir::split(&f, &mut r, &s, K, N);
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(proactive::refresh(&f, &mut r, &shares, K));
}
ms_per_op(t0.elapsed(), n_iter)
}
"proactive_recover" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let shares = shamir::split(&f, &mut r, &s, K, N);
let live = vec![shares[0].clone(), shares[1].clone(), shares[3].clone()];
let lost_x = shares[2].x.clone();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(proactive::recover_share(&f, &live, K, &lost_x).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"bytes_split_16" => {
let f = field();
let mut r = rng();
let secret = vec![0xC3u8; 16];
let n_iter = iters(1000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(bytes::split(&f, &mut r, &secret, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"bytes_reconstruct_16" => {
let f = field();
let mut r = rng();
let secret = vec![0xC3u8; 16];
let shares = bytes::split(&f, &mut r, &secret, K, N);
let refs: Vec<&[u8]> = shares.iter().map(Vec::as_slice).collect();
let n_iter = iters(1000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(bytes::reconstruct(&f, &refs[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"ida_split_16" => {
let f = field();
let data = vec![0x5Au8; 16];
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(ida::split(&f, &data, K, N));
}
ms_per_op(t0.elapsed(), n_iter)
}
"ida_reconstruct_16" => {
let f = field();
let data = vec![0x5Au8; 16];
let shares = ida::split(&f, &data, K, N);
let refs: Vec<&[u8]> = shares.iter().map(Vec::as_slice).collect();
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(ida::reconstruct(&f, &refs[..K], K).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"decode_reconstruct_t1" => {
let f = field();
let mut r = rng();
let s = f.random(&mut r);
let mut shares = shamir::split(&f, &mut r, &s, K, 11);
shares[3].y = f.add(&shares[3].y, &BigUint::from_u64(1));
let n_iter = iters(200);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(reconstruct_with_errors(&f, &shares, K, 1).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"visual_split_3_8" => {
let mut r = rng();
let secret: Vec<Vec<bool>> = (0..8)
.map(|y| (0..8).map(|x| (x + y) % 2 == 0).collect())
.collect();
let n_iter = iters(500);
let t0 = Instant::now();
for _ in 0..n_iter {
black_box(visual::split_n_of_n(&mut r, &secret, 3));
}
ms_per_op(t0.elapsed(), n_iter)
}
"visual_decode_3_8" => {
let mut r = rng();
let secret: Vec<Vec<bool>> = (0..8)
.map(|y| (0..8).map(|x| (x + y) % 2 == 0).collect())
.collect();
let shares = visual::split_n_of_n(&mut r, &secret, 3);
let n_iter = iters(2000);
let t0 = Instant::now();
for _ in 0..n_iter {
let stacked = visual::stack(&shares).unwrap();
black_box(visual::decode(&stacked, 3).unwrap());
}
ms_per_op(t0.elapsed(), n_iter)
}
"shamir_split_4kb" => {
let f = field();
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for s in &chunks {
black_box(shamir::split(&f, &mut r, s, K, N));
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"shamir_reconstruct_4kb" => {
let f = field();
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let share_chunks: Vec<Vec<shamir::Share>> = chunks
.iter()
.map(|s| shamir::split(&f, &mut r, s, K, N))
.collect();
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for shares in &share_chunks {
black_box(shamir::reconstruct(&f, &shares[..K], K).unwrap());
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"blakley_split_4kb" => {
let f = field();
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for s in &chunks {
black_box(blakley::split(&f, &mut r, s, K, N));
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"blakley_reconstruct_4kb" => {
let f = field();
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let share_chunks: Vec<_> = chunks
.iter()
.map(|s| blakley::split(&f, &mut r, s, K, N))
.collect();
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for shares in &share_chunks {
black_box(blakley::reconstruct(&f, &shares[..K], K).unwrap());
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"kothari_split_4kb" => {
let scheme = kothari::vandermonde(field(), K, N);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for s in &chunks {
black_box(kothari::split(&scheme, &mut r, s));
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"kothari_reconstruct_4kb" => {
let scheme = kothari::vandermonde(field(), K, N);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let share_chunks: Vec<Vec<(usize, BigUint)>> = chunks
.iter()
.map(|s| {
let shares = kothari::split(&scheme, &mut r, s);
(0..K).map(|c| (c, shares[c].clone())).collect()
})
.collect();
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for pairs in &share_chunks {
black_box(kothari::reconstruct(&scheme, pairs).unwrap());
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"karchmer_wigderson_split_4kb" => {
let prog = kw::threshold_msp(field(), K, N);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for s in &chunks {
black_box(kw::split(&prog, &mut r, s));
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"karchmer_wigderson_reconstruct_4kb" => {
let prog = kw::threshold_msp(field(), K, N);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let coalition_chunks: Vec<Vec<_>> = chunks
.iter()
.map(|s| {
let shares = kw::split(&prog, &mut r, s);
shares.iter().take(K).cloned().collect()
})
.collect();
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for coalition in &coalition_chunks {
black_box(kw::reconstruct(&prog, coalition).unwrap());
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"brickell_split_4kb" => {
let f = field();
let vectors: Vec<Vec<BigUint>> = (1..=N)
.map(|j| {
let mut row = Vec::with_capacity(K);
let mut pow = BigUint::one();
let j_val = BigUint::from_u64(j as u64);
for _ in 0..K {
row.push(pow.clone());
pow = f.mul(&pow, &j_val);
}
row
})
.collect();
let scheme = brickell::Scheme::new(f.clone(), vectors);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for s in &chunks {
black_box(brickell::split(&scheme, &mut r, s));
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"brickell_reconstruct_4kb" => {
let f = field();
let vectors: Vec<Vec<BigUint>> = (1..=N)
.map(|j| {
let mut row = Vec::with_capacity(K);
let mut pow = BigUint::one();
let j_val = BigUint::from_u64(j as u64);
for _ in 0..K {
row.push(pow.clone());
pow = f.mul(&pow, &j_val);
}
row
})
.collect();
let scheme = brickell::Scheme::new(f.clone(), vectors);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let coalition_chunks: Vec<Vec<_>> = chunks
.iter()
.map(|s| {
let shares = brickell::split(&scheme, &mut r, s);
shares.iter().take(K).cloned().collect()
})
.collect();
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for coalition in &coalition_chunks {
black_box(brickell::reconstruct(&scheme, coalition).unwrap());
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"massey_split_4kb" => {
let f = field();
let mut g = vec![vec![BigUint::one(); N + 1], vec![BigUint::zero(); N + 1]];
#[allow(clippy::needless_range_loop)]
for j in 1..=N {
g[1][j] = BigUint::from_u64(j as u64);
}
let scheme = massey::CodeScheme::new(f.clone(), g);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for s in &chunks {
black_box(massey::split(&scheme, &mut r, s));
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"massey_reconstruct_4kb" => {
let f = field();
let mut g = vec![vec![BigUint::one(); N + 1], vec![BigUint::zero(); N + 1]];
#[allow(clippy::needless_range_loop)]
for j in 1..=N {
g[1][j] = BigUint::from_u64(j as u64);
}
let scheme = massey::CodeScheme::new(f.clone(), g);
let mut r = rng();
let chunks = chunks_4kb(&mut r);
let coalition_chunks: Vec<Vec<_>> = chunks
.iter()
.map(|s| {
let shares = massey::split(&scheme, &mut r, s);
shares.iter().take(2).cloned().collect()
})
.collect();
let n_iter = iters(20);
let t0 = Instant::now();
for _ in 0..n_iter {
for coalition in &coalition_chunks {
black_box(massey::reconstruct(&scheme, coalition).unwrap());
}
}
ms_per_op(t0.elapsed(), n_iter)
}
"shamir_split_2_3" => shamir_split_kn(2, 3),
"shamir_split_3_5" => shamir_split_kn(3, 5),
"shamir_split_5_9" => shamir_split_kn(5, 9),
"shamir_split_7_15" => shamir_split_kn(7, 15),
"shamir_split_10_20" => shamir_split_kn(10, 20),
"shamir_reconstruct_2_3" => shamir_reconstruct_kn(2, 3),
"shamir_reconstruct_3_5" => shamir_reconstruct_kn(3, 5),
"shamir_reconstruct_5_9" => shamir_reconstruct_kn(5, 9),
"shamir_reconstruct_7_15" => shamir_reconstruct_kn(7, 15),
"shamir_reconstruct_10_20" => shamir_reconstruct_kn(10, 20),
"shamir_cold_split" => shamir_cold_split(),
"shamir_cold_reconstruct" => shamir_cold_reconstruct(),
"blakley_cold_split" => blakley_cold_split(),
"blakley_cold_reconstruct" => blakley_cold_reconstruct(),
"massey_cold_split" => massey_cold_split(),
"massey_cold_reconstruct" => massey_cold_reconstruct(),
other => {
eprintln!("unknown operation: {other}");
std::process::exit(2);
}
};
println!("{ms}");
}