primitives/sharing/authenticated/pairwise/
mod.rs1pub 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::{
13 binary::{Gf2_128, Gf2_128Field},
14 FieldElement,
15 FieldExtension,
16 },
17 random::{BaseRng, Random, RandomWith, Seed, SeedableRng},
18};
19
20pub trait PairwiseAuthenticated: RandomWith<Vec<Self::GlobalAuthKey>> {
22 type GlobalAuthKey: Random + Clone + Any;
24
25 fn get_global_keys(&self) -> impl ExactSizeIterator<Item = Self::GlobalAuthKey>;
27
28 fn deal_global_keys(
30 n_parties: usize,
31 seed: Seed,
32 compatibility: bool,
33 ) -> Vec<Vec<Self::GlobalAuthKey>> {
34 let rng = if compatibility {
35 BaseRng::from_seed(seed)
36 } else {
37 BaseRng::from_tagged_seed(seed, std::any::type_name::<Self::GlobalAuthKey>())
38 };
39 let mut alphas: Vec<Vec<Self::GlobalAuthKey>> =
40 Vec::<Self::GlobalAuthKey>::random_n_with(rng, n_parties, n_parties - 1);
41 if !compatibility {
42 force_binary_lsb_constraint::<Self::GlobalAuthKey, Gf2_128>(&mut alphas, n_parties);
46 force_binary_lsb_constraint::<Self::GlobalAuthKey, Gf2_128Field>(
47 &mut alphas,
48 n_parties,
49 );
50 }
51 alphas
52 }
53}
54
55fn force_binary_lsb_constraint<K: Any, F: FieldExtension>(alphas: &mut [Vec<K>], n_parties: usize) {
65 if TypeId::of::<K>() != TypeId::of::<GlobalFieldKey<F>>() {
66 return;
67 }
68 for (i, alphas_i) in alphas.iter_mut().enumerate() {
69 for j in 0..n_parties {
70 if i == j {
71 continue;
72 }
73 let pos = if j < i { j } else { j - 1 };
74 let target_lsb = u8::from(i > j);
75 let key: &mut GlobalFieldKey<F> = (&mut alphas_i[pos] as &mut dyn Any)
76 .downcast_mut()
77 .expect("TypeId guarantees this cast");
78 let current = key.inner();
79 if current.to_le_bytes()[0] & 1 != target_lsb {
80 *key = GlobalFieldKey::<F>::new(FieldElement::new(current + F::from(1u128)));
81 }
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::sharing::FieldShare;
90
91 fn assert_lsb_constraint<F: FieldExtension>()
92 where
93 FieldShare<F>: PairwiseAuthenticated<GlobalAuthKey = GlobalFieldKey<F>>,
94 {
95 let n_parties = 4;
96 let seed = Seed::default();
97 let alphas = FieldShare::<F>::deal_global_keys(n_parties, seed, false);
98 for (i, alphas_i) in alphas.iter().enumerate() {
99 for j in 0..n_parties {
100 if i == j {
101 continue;
102 }
103 let pos = if j < i { j } else { j - 1 };
104 let lsb = alphas_i[pos].inner().to_le_bytes()[0] & 1;
105 assert_eq!(lsb, u8::from(i > j), "lsb(Δ_{i}{j}) violates the DPF shape");
106 }
107 }
108 }
109
110 #[test]
111 fn binary_global_keys_have_dpf_lsb_shape() {
112 assert_lsb_constraint::<Gf2_128>();
113 assert_lsb_constraint::<Gf2_128Field>();
114 }
115}