Skip to main content

primitives/sharing/authenticated/pairwise/
mod.rs

1pub mod keys;
2pub mod open_share;
3pub mod share;
4
5use std::any::{Any, TypeId};
6
7pub use keys::*;
8pub use open_share::*;
9pub use share::*;
10
11use crate::{
12    algebra::field::{binary::Gf2_128, FieldElement, FieldExtension},
13    random::{BaseRng, Random, RandomWith, Seed, SeedableRng},
14};
15
16/// A trait for secret shares that hold keys for pairwise authentication.
17pub trait PairwiseAuthenticated {
18    /// Global keys used to authenticate the shares of all other parties.
19    type GlobalAuthKey: Random + Clone + Any;
20
21    /// Get the global keys used to authenticate the shares of every other party.
22    fn get_global_keys(&self) -> impl ExactSizeIterator<Item = Self::GlobalAuthKey>;
23
24    /// Deal global keys used to authenticate the shares of all parties.
25    fn deal_global_keys(
26        n_parties: usize,
27        seed: Seed,
28        compatibility: bool,
29    ) -> Vec<Vec<Self::GlobalAuthKey>> {
30        let rng = if compatibility {
31            BaseRng::from_seed(seed)
32        } else {
33            BaseRng::from_tagged_seed(seed, std::any::type_name::<Self::GlobalAuthKey>())
34        };
35        let mut alphas: Vec<Vec<Self::GlobalAuthKey>> =
36            Vec::<Self::GlobalAuthKey>::random_n_with(rng, n_parties, n_parties - 1);
37        if !compatibility {
38            // DPF/SPFSS over binary global MAC keys requires the per-pair invariant
39            //   lsb(Δ_ij) = 0 if i < j, else 1
40            // where Δ_ij is the key party i holds for party j. This implies the
41            // 2-party condition lsb(Δ_01 ⊕ Δ_10) = 1 and generalizes it for n > 2.
42            if TypeId::of::<Self::GlobalAuthKey>() == TypeId::of::<GlobalFieldKey<Gf2_128>>() {
43                for (i, alphas_i) in alphas.iter_mut().enumerate() {
44                    for j in 0..n_parties {
45                        if i == j {
46                            continue;
47                        }
48                        let pos = if j < i { j } else { j - 1 };
49                        let target_lsb = u8::from(i > j);
50                        let key: &mut GlobalFieldKey<Gf2_128> = (&mut alphas_i[pos]
51                            as &mut dyn Any)
52                            .downcast_mut()
53                            .expect("TypeId guarantees this cast");
54                        let current = key.inner();
55                        if current.to_le_bytes()[0] & 1 != target_lsb {
56                            *key = GlobalFieldKey::<Gf2_128>::new(FieldElement::new(
57                                current + Gf2_128::from(1u128),
58                            ));
59                        }
60                    }
61                }
62            }
63        }
64        alphas
65    }
66}