pub mod keys;
pub mod open_share;
pub mod share;
use std::any::{Any, TypeId};
pub use keys::*;
pub use open_share::*;
pub use share::*;
use crate::{
algebra::field::{
binary::{Gf2_128, Gf2_128Field},
FieldElement,
FieldExtension,
},
random::{BaseRng, Random, RandomWith, Seed, SeedableRng},
};
pub trait PairwiseAuthenticated: RandomWith<Vec<Self::GlobalAuthKey>> {
type GlobalAuthKey: Random + Clone + Any;
fn get_global_keys(&self) -> impl ExactSizeIterator<Item = Self::GlobalAuthKey>;
fn deal_global_keys(
n_parties: usize,
seed: Seed,
compatibility: bool,
) -> Vec<Vec<Self::GlobalAuthKey>> {
let rng = if compatibility {
BaseRng::from_seed(seed)
} else {
BaseRng::from_tagged_seed(seed, std::any::type_name::<Self::GlobalAuthKey>())
};
let mut alphas: Vec<Vec<Self::GlobalAuthKey>> =
Vec::<Self::GlobalAuthKey>::random_n_with(rng, n_parties, n_parties - 1);
if !compatibility {
force_binary_lsb_constraint::<Self::GlobalAuthKey, Gf2_128>(&mut alphas, n_parties);
force_binary_lsb_constraint::<Self::GlobalAuthKey, Gf2_128Field>(
&mut alphas,
n_parties,
);
}
alphas
}
}
fn force_binary_lsb_constraint<K: Any, F: FieldExtension>(alphas: &mut [Vec<K>], n_parties: usize) {
if TypeId::of::<K>() != TypeId::of::<GlobalFieldKey<F>>() {
return;
}
for (i, alphas_i) in alphas.iter_mut().enumerate() {
for j in 0..n_parties {
if i == j {
continue;
}
let pos = if j < i { j } else { j - 1 };
let target_lsb = u8::from(i > j);
let key: &mut GlobalFieldKey<F> = (&mut alphas_i[pos] as &mut dyn Any)
.downcast_mut()
.expect("TypeId guarantees this cast");
let current = key.inner();
if current.to_le_bytes()[0] & 1 != target_lsb {
*key = GlobalFieldKey::<F>::new(FieldElement::new(current + F::from(1u128)));
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sharing::FieldShare;
fn assert_lsb_constraint<F: FieldExtension>()
where
FieldShare<F>: PairwiseAuthenticated<GlobalAuthKey = GlobalFieldKey<F>>,
{
let n_parties = 4;
let seed = Seed::default();
let alphas = FieldShare::<F>::deal_global_keys(n_parties, seed, false);
for (i, alphas_i) in alphas.iter().enumerate() {
for j in 0..n_parties {
if i == j {
continue;
}
let pos = if j < i { j } else { j - 1 };
let lsb = alphas_i[pos].inner().to_le_bytes()[0] & 1;
assert_eq!(lsb, u8::from(i > j), "lsb(Δ_{i}{j}) violates the DPF shape");
}
}
}
#[test]
fn binary_global_keys_have_dpf_lsb_shape() {
assert_lsb_constraint::<Gf2_128>();
assert_lsb_constraint::<Gf2_128Field>();
}
}