Skip to main content

primitives/sharing/authenticated/
field_share.rs

1use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3use itertools::enumerate;
4use num_traits::Zero;
5use serde::{Deserialize, Serialize};
6use subtle::{Choice, ConstantTimeEq};
7
8use super::{FieldShareKey, GlobalFieldKey};
9use crate::{
10    algebra::field::{FieldElement, FieldExtension, SubfieldElement},
11    errors::PrimitiveError,
12    izip_eq,
13    random::{CryptoRngCore, Random, RandomWith},
14    sharing::{
15        authenticated::NParties,
16        unauthenticated::AdditiveShares,
17        AddPlaintext,
18        IsFirstPeer,
19        Reconstructible,
20        VerifiableWith,
21    },
22    types::{CollectAll, ConditionallySelectable, PeerIndex},
23    utils::IntoExactSizeIterator,
24};
25#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
26#[serde(bound = "F: FieldExtension")]
27pub struct OpenFieldShare<F: FieldExtension> {
28    pub(crate) value: SubfieldElement<F>,
29    pub(crate) mac: FieldElement<F>,
30}
31
32impl<F: FieldExtension> OpenFieldShare<F> {
33    pub fn new(value: SubfieldElement<F>, mac: FieldElement<F>) -> Self {
34        Self { value, mac }
35    }
36
37    pub fn get_value(&self) -> &SubfieldElement<F> {
38        &self.value
39    }
40
41    pub fn get_mac(&self) -> &FieldElement<F> {
42        &self.mac
43    }
44}
45
46/// Authenticated share <x_i> of secret shared <x> held by `P_i` (this party).
47///
48/// They are composed of:
49/// - `x_i`, the unauthenticated share value (s.t. `x = Σ x_i`)
50/// - `{MAC(x_i)_j} ∀j∈[1..n]∖{i}`, the MACs of `x_i` for each of the other n-1 parties.
51/// - `{β_ij} ∀j∈[1..n]∖{i}` and `{α_ij} ∀j∈[1..n]∖{i}`, the (local and global) keys tied to the
52///   values&MACs of the other n-1 parties.
53///
54/// The authenticated shares fulfill this relation:
55///
56/// ```MAC(x_i)_j = α_ji · x_i + β_ji  ∀i∈[1..n]  ∀j∈[1..n]∖{i}```
57///     
58/// where `β_ji` and `α_ji` are the (local and global) keys of x_i held by P_j.
59#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
60#[serde(bound = "F: FieldExtension")]
61pub struct FieldShare<F>
62where
63    F: FieldExtension,
64{
65    pub(crate) value: SubfieldElement<F>,     // x_i
66    pub(crate) macs: Box<[FieldElement<F>]>,  // {MAC(x_i)_j} ∀j∈[1..n]∖{i}
67    pub(crate) keys: Box<[FieldShareKey<F>]>, // {(α_ij, β_ij)} ∀j∈[1..n]∖{i}
68}
69
70impl<F: FieldExtension> FieldShare<F> {
71    pub fn try_new(
72        value: SubfieldElement<F>,
73        macs: Box<[FieldElement<F>]>,
74        keys: Box<[FieldShareKey<F>]>,
75    ) -> Result<Self, PrimitiveError> {
76        if macs.is_empty() {
77            return Err(PrimitiveError::MinimumLength(2, 0));
78        }
79        if macs.len() != keys.len() {
80            return Err(PrimitiveError::InvalidSize(keys.len(), macs.len()));
81        }
82        /* NOTE: We assume length equality for macs & keys from this point on */
83        Ok(Self { value, macs, keys })
84    }
85
86    pub(super) fn new(
87        value: SubfieldElement<F>,
88        macs: Box<[FieldElement<F>]>,
89        keys: Box<[FieldShareKey<F>]>,
90    ) -> Self {
91        Self { value, macs, keys }
92    }
93
94    pub fn zero_from_alphas(alphas: impl ExactSizeIterator<Item = GlobalFieldKey<F>>) -> Self {
95        let n_peers = alphas.len();
96        FieldShare {
97            value: SubfieldElement::zero(),
98            macs: vec![FieldElement::<F>::zero(); n_peers].into_boxed_slice(),
99            keys: alphas
100                .map(|alpha| FieldShareKey::<F>::new(alpha, FieldElement::zero()))
101                .collect(),
102        }
103    }
104
105    #[inline]
106    pub fn get_value(&self) -> &SubfieldElement<F> {
107        &self.value
108    }
109
110    #[inline]
111    pub fn value(self) -> SubfieldElement<F> {
112        self.value
113    }
114
115    #[inline]
116    pub fn get_macs(&self) -> &[FieldElement<F>] {
117        &self.macs
118    }
119
120    #[inline]
121    pub fn get_mac(&self, peer_index: PeerIndex) -> Option<&FieldElement<F>> {
122        self.macs.get(peer_index)
123    }
124
125    #[inline]
126    pub fn get_keys(&self) -> &[FieldShareKey<F>] {
127        &self.keys
128    }
129
130    #[inline]
131    pub fn get_key(&self, peer_index: PeerIndex) -> Option<&FieldShareKey<F>> {
132        self.keys.get(peer_index)
133    }
134
135    #[inline]
136    pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalFieldKey<F>> + '_ {
137        self.keys.iter().map(|key| key.get_alpha())
138    }
139
140    #[inline]
141    pub fn n_parties(&self) -> usize {
142        self.macs.len() + 1 // +1 for the local share
143    }
144}
145
146// --------------------
147// |   Verification   |
148// --------------------
149impl<F: FieldExtension> VerifiableWith for FieldShare<F> {
150    type VerificationData = ();
151
152    /// Check the MACs of the share received from another peer.
153    #[inline]
154    fn verify_from_peer_with(
155        &self,
156        open_share: &OpenFieldShare<F>,
157        peer: PeerIndex,
158        _verification_data: (),
159    ) -> Result<(), PrimitiveError> {
160        self.get_key(peer)
161            .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?
162            .verify_mac(open_share)
163            .map_err(|e| e.blame(peer))
164    }
165
166    /// Check the MACs of each share received from all other peers.
167    #[inline]
168    fn verify_with(
169        &self,
170        open_shares: &[OpenFieldShare<F>],
171        _verification_data: (),
172    ) -> Result<(), PrimitiveError> {
173        enumerate(izip_eq!(open_shares, &self.keys))
174            .map(|(from_peer, (open_share, key))| {
175                key.verify_mac(open_share).map_err(|e| e.blame(from_peer))
176            })
177            .collect_errors()?;
178        Ok(())
179    }
180}
181
182// --------------------------------
183// |   Opening & Reconstruction   |
184// --------------------------------
185
186impl<F: FieldExtension> Reconstructible for FieldShare<F> {
187    type Opening = OpenFieldShare<F>;
188    type Secret = SubfieldElement<F>;
189
190    /// Open the share towards another peer.
191    fn open_to(&self, peer: PeerIndex) -> Result<OpenFieldShare<F>, PrimitiveError> {
192        let mac = self
193            .get_mac(peer)
194            .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.macs.len()))?
195            .to_owned();
196        Ok(OpenFieldShare::new(self.get_value().to_owned(), mac))
197    }
198
199    /// Open the share towards all other peers.
200    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenFieldShare<F>> {
201        self.get_macs()
202            .iter()
203            .map(|mac| OpenFieldShare::new(self.get_value().to_owned(), mac.to_owned()))
204    }
205
206    /// Reconstruct a secret from openings coming from all other parties.
207    fn reconstruct(&self, openings: &[OpenFieldShare<F>]) -> Result<Self::Secret, PrimitiveError> {
208        if openings.len() != self.get_keys().len() {
209            return Err(PrimitiveError::InvalidSize(
210                self.get_keys().len(),
211                openings.len(),
212            ));
213        }
214        self.verify_with(openings, ())?;
215        Ok(openings
216            .iter()
217            .fold(self.get_value().to_owned(), |acc, open_share| {
218                acc + open_share.get_value()
219            }))
220    }
221}
222
223// -------------------------
224// |   Random Generation   |
225// -------------------------
226
227fn compute_macs<F: FieldExtension>(
228    all_unauth_shares: &[SubfieldElement<F>],
229    all_keys: &[Box<[FieldShareKey<F>]>],
230) -> Vec<Box<[FieldElement<F>]>> {
231    let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
232    enumerate(all_unauth_shares.iter())
233        .map(|(i, my_unauth_share)| {
234            enumerate(all_key_iters.iter_mut())
235                .filter(|(j, _)| *j != i)
236                .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
237                .collect()
238        })
239        .collect()
240}
241
242impl<F: FieldExtension> Random for FieldShare<F> {
243    fn random(_rng: impl CryptoRngCore) -> Self {
244        unimplemented!(
245            "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
246            std::any::type_name::<Self>()
247        )
248    }
249
250    /// Generate one random field share per peer, with consistent MACs and keys across all peers.
251    fn random_n<Container: FromIterator<Self>>(
252        mut rng: impl CryptoRngCore,
253        n_parties: usize,
254    ) -> Container {
255        let all_unauth_shares: Vec<_> = SubfieldElement::random_n(&mut rng, n_parties);
256        let all_keys = (0..n_parties)
257            .map(|_| FieldShareKey::<F>::random_n(&mut rng, n_parties - 1))
258            .collect::<Vec<_>>();
259        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
260        izip_eq!(all_unauth_shares, all_macs, all_keys)
261            .map(|(value, macs, keys)| FieldShare { value, macs, keys })
262            .collect()
263    }
264}
265
266impl<F: FieldExtension> RandomWith<NParties> for FieldShare<F> {
267    /// Generate a random field share, with Macs and keys for all the other parties.
268    fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
269        FieldShare {
270            value: SubfieldElement::random(&mut rng),
271            macs: FieldElement::<F>::random_n(&mut rng, n_parties - 1),
272            keys: FieldShareKey::<F>::random_n(&mut rng, n_parties - 1),
273        }
274    }
275}
276
277impl<F: FieldExtension> RandomWith<(NParties, SubfieldElement<F>)> for FieldShare<F> {
278    /// Generate a random field share, with Macs and keys for all the other parties.
279    fn random_with(
280        mut rng: impl CryptoRngCore,
281        n_parties_and_value: (NParties, SubfieldElement<F>),
282    ) -> Self {
283        let (n_parties, value) = n_parties_and_value;
284        FieldShare {
285            value,
286            macs: FieldElement::<F>::random_n(&mut rng, n_parties - 1),
287            keys: FieldShareKey::<F>::random_n(&mut rng, n_parties - 1),
288        }
289    }
290}
291
292impl<F: FieldExtension> RandomWith<SubfieldElement<F>> for FieldShare<F> {
293    fn random_with(_rng: impl CryptoRngCore, _data: SubfieldElement<F>) -> Self {
294        unimplemented!(
295            "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
296            std::any::type_name::<Self>()
297        )
298    }
299
300    /// Secret share a value among n parties, generating an authenticated share for each
301    /// peer with consistent MACs and keys across all peers.
302    fn random_n_with<Container: FromIterator<Self>>(
303        mut rng: impl CryptoRngCore,
304        n_parties: usize,
305        value: SubfieldElement<F>,
306    ) -> Container {
307        let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
308        let all_keys = (0..n_parties)
309            .map(|_| FieldShareKey::<F>::random_n(&mut rng, n_parties - 1))
310            .collect::<Vec<_>>();
311        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
312        izip_eq!(all_unauth_shares, all_macs, all_keys)
313            .map(|(value, macs, keys)| FieldShare { value, macs, keys })
314            .collect()
315    }
316}
317
318impl<F: FieldExtension> RandomWith<Vec<GlobalFieldKey<F>>> for FieldShare<F> {
319    /// Generate a random field share from its global keys (alphas).
320    fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
321        let n_other_parties = alphas.len();
322        FieldShare {
323            value: SubfieldElement::random(&mut rng),
324            macs: FieldElement::<F>::random_n(&mut rng, n_other_parties),
325            keys: FieldShareKey::<F>::random_n_with_each(&mut rng, alphas),
326        }
327    }
328
329    /// Generate one random field share per peer from their global keys (alphas).
330    fn random_n_with_each<Container: FromIterator<Self>>(
331        mut rng: impl CryptoRngCore,
332        all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
333    ) -> Container {
334        let all_alphas = all_alphas.into_iter();
335        let all_unauth_shares: Vec<_> = SubfieldElement::random_n(&mut rng, all_alphas.len());
336        let all_keys = all_alphas
337            .into_iter()
338            .map(|my_alphas| FieldShareKey::<F>::random_n_with_each(&mut rng, my_alphas))
339            .collect::<Vec<_>>();
340        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
341        izip_eq!(all_unauth_shares, all_macs, all_keys)
342            .map(|(value, macs, keys)| FieldShare { value, macs, keys })
343            .collect()
344    }
345}
346
347impl<F: FieldExtension> RandomWith<(SubfieldElement<F>, Vec<GlobalFieldKey<F>>)> for FieldShare<F> {
348    /// Generate a random field share from its global keys (alphas) and its share
349    fn random_with(
350        mut rng: impl CryptoRngCore,
351        value_alphas: (SubfieldElement<F>, Vec<GlobalFieldKey<F>>),
352    ) -> Self {
353        let (value, alphas) = value_alphas;
354        let n_other_parties = alphas.len();
355        FieldShare {
356            value,
357            macs: FieldElement::<F>::random_n(&mut rng, n_other_parties),
358            keys: FieldShareKey::<F>::random_n_with_each(&mut rng, alphas),
359        }
360    }
361
362    /// Generate one random field share per peer from their global keys (alphas).
363    fn random_n_with_each<Container: FromIterator<Self>>(
364        mut rng: impl CryptoRngCore,
365        unauth_shares_and_alphas: impl IntoExactSizeIterator<
366            Item = (SubfieldElement<F>, Vec<GlobalFieldKey<F>>),
367        >,
368    ) -> Container {
369        let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
370            .into_iter()
371            .map(|(value, my_alphas)| {
372                (
373                    value,
374                    FieldShareKey::<F>::random_n_with_each(&mut rng, my_alphas),
375                )
376            })
377            .unzip();
378        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
379        izip_eq!(all_unauth_shares, all_macs, all_keys)
380            .map(|(value, macs, keys)| FieldShare { value, macs, keys })
381            .collect()
382    }
383}
384
385impl<F: FieldExtension> RandomWith<(SubfieldElement<F>, Vec<Vec<GlobalFieldKey<F>>>)>
386    for FieldShare<F>
387{
388    fn random_with(
389        _source: impl CryptoRngCore,
390        _data: (SubfieldElement<F>, Vec<Vec<GlobalFieldKey<F>>>),
391    ) -> Self {
392        unimplemented!(
393            "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
394        );
395    }
396
397    /// Generate a random field share per peer from a value to secret share and global keys
398    /// (alphas).
399    fn random_n_with<Container: FromIterator<Self>>(
400        mut rng: impl CryptoRngCore,
401        n_parties: usize,
402        (secret_value, all_alphas): (SubfieldElement<F>, Vec<Vec<GlobalFieldKey<F>>>),
403    ) -> Container {
404        if n_parties != all_alphas.len() {
405            panic!("n_parties does not match the number of alphas provided");
406        }
407
408        let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
409        let all_keys = all_alphas
410            .into_iter()
411            .map(|my_alphas| FieldShareKey::<F>::random_n_with_each(&mut rng, my_alphas))
412            .collect::<Vec<_>>();
413        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
414        izip_eq!(all_unauth_shares, all_macs, all_keys)
415            .map(|(value, macs, keys)| FieldShare { value, macs, keys })
416            .collect()
417    }
418}
419
420// --------------
421// | Arithmetic |
422// --------------
423
424// === Addition === //
425
426#[macros::op_variants(owned, borrowed, flipped_commutative)]
427impl<'a, F: FieldExtension> Add<&'a FieldShare<F>> for FieldShare<F> {
428    type Output = FieldShare<F>;
429
430    #[inline]
431    fn add(mut self, other: &'a FieldShare<F>) -> Self::Output {
432        self.value += &other.value;
433        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
434        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
435        self
436    }
437}
438
439#[macros::op_variants(owned)]
440impl<'a, F: FieldExtension> AddAssign<&'a FieldShare<F>> for FieldShare<F> {
441    #[inline]
442    fn add_assign(&mut self, other: &'a FieldShare<F>) {
443        self.value += &other.value;
444        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
445        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
446    }
447}
448
449// === Subtraction === //
450
451#[macros::op_variants(owned, borrowed, flipped)]
452impl<'a, F: FieldExtension> Sub<&'a FieldShare<F>> for FieldShare<F> {
453    type Output = FieldShare<F>;
454
455    #[inline]
456    fn sub(mut self, other: &'a FieldShare<F>) -> Self::Output {
457        self.value -= &other.value;
458        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
459        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
460        self
461    }
462}
463
464#[macros::op_variants(owned)]
465impl<'a, F: FieldExtension> SubAssign<&'a FieldShare<F>> for FieldShare<F> {
466    #[inline]
467    fn sub_assign(&mut self, other: &'a FieldShare<F>) {
468        self.value -= &other.value;
469        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
470        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
471    }
472}
473
474// === Constant multiplication === //
475
476#[macros::op_variants(owned, borrowed, flipped)]
477impl<'a, F: FieldExtension> Mul<&'a SubfieldElement<F>> for FieldShare<F> {
478    type Output = FieldShare<F>;
479
480    #[inline]
481    fn mul(mut self, other: &'a SubfieldElement<F>) -> FieldShare<F> {
482        self.value *= other;
483        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
484        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
485        self
486    }
487}
488
489// === MulAssign === //
490
491#[macros::op_variants(owned)]
492impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for FieldShare<F> {
493    #[inline]
494    fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
495        self.value *= other;
496        izip_eq!(&mut self.keys).for_each(|key| *key *= other);
497        izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
498    }
499}
500
501// === Negation === //
502
503#[macros::op_variants(borrowed)]
504impl<F: FieldExtension> Neg for FieldShare<F> {
505    type Output = FieldShare<F>;
506
507    #[inline]
508    fn neg(self) -> Self::Output {
509        FieldShare {
510            value: -self.value,
511            keys: self.keys.iter().map(|key| -key).collect(),
512            macs: self.macs.iter().map(|mac| -mac).collect(),
513        }
514    }
515}
516
517// === Constant addition / subtraction === //
518
519impl<F: FieldExtension> AddPlaintext for FieldShare<F> {
520    type AssociatedInformation = IsFirstPeer;
521    /// Adds a plaintext to the secret shared value, updating the keys accordingly.
522    /// A designated peer (P_0) will modify its value, while the other peers will update their keys.
523    #[inline]
524    fn add_plaintext(&self, plaintext: &SubfieldElement<F>, is_peer_zero: IsFirstPeer) -> Self {
525        let result = self.clone();
526        result.add_plaintext_owned(plaintext, is_peer_zero)
527    }
528
529    /// Adds a plaintext to the secret shared value, updating the keys accordingly.
530    /// A designated peer (P_0) will modify its value, while the other peers will update their keys.
531    #[inline]
532    fn add_plaintext_owned(
533        mut self,
534        plaintext: &SubfieldElement<F>,
535        is_peer_zero: IsFirstPeer,
536    ) -> Self {
537        if is_peer_zero {
538            self.value += plaintext;
539        } else {
540            let key0 = self.keys.get_mut(0).expect("Missing key 0");
541            key0.beta -= *key0.alpha * plaintext;
542        }
543        self
544    }
545}
546
547// ---------------------------------------
548// |  Constant time Selection / Equality |
549// ---------------------------------------
550
551impl<F: FieldExtension> ConstantTimeEq for FieldShare<F> {
552    #[inline]
553    fn ct_eq(&self, other: &Self) -> Choice {
554        self.value.ct_eq(&other.value) & self.keys.ct_eq(&other.keys) & self.macs.ct_eq(&other.macs)
555    }
556}
557
558impl<F: FieldExtension> ConditionallySelectable for FieldShare<F> {
559    #[inline]
560    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
561        FieldShare {
562            value: SubfieldElement::conditional_select(&a.value, &b.value, choice),
563            macs: izip_eq!(&a.macs, &b.macs)
564                .map(|(a_mac, b_mac)| FieldElement::conditional_select(a_mac, b_mac, choice))
565                .collect(),
566            keys: izip_eq!(&a.keys, &b.keys)
567                .map(|(a_key, b_key)| FieldShareKey::conditional_select(a_key, b_key, choice))
568                .collect(),
569        }
570    }
571}
572
573#[cfg(test)]
574mod tests {
575    use itertools::enumerate;
576
577    use super::*;
578    use crate::{
579        algebra::elliptic_curve::{Curve25519Ristretto as C, Scalar},
580        random::{self},
581        sharing::{GlobalScalarKey, ScalarShare, Verifiable},
582    };
583
584    // TODO: Generalize once PairwiseAuthenticatedShare trait is implemented.
585
586    //////////////////////////////////////////////////
587    // CHANGE ONLY THESE TO TEST ANOTHER SHARE TYPE //
588    pub type Value = Scalar<C>;
589    pub type Constant = Scalar<C>;
590    pub type Share = ScalarShare<C>;
591    pub type GlobalKey = GlobalScalarKey<C>;
592    //////////////////////////////////////////////////
593
594    pub const N_PARTIES: usize = 3;
595
596    #[test]
597    fn test_open_to() {
598        let mut rng = random::test_rng();
599        let local_share = Share::random_with(&mut rng, N_PARTIES);
600
601        for i in 0..N_PARTIES - 1 {
602            let open_share = local_share.open_to(i).unwrap();
603            assert_eq!(open_share.get_value(), &local_share.value);
604            assert_eq!(open_share.get_mac(), &local_share.macs[i]);
605        }
606    }
607
608    #[test]
609    fn test_random() {
610        let mut rng = random::test_rng();
611
612        // Generate a completely random share
613        let share = Share::random_with(&mut rng, N_PARTIES);
614        assert_eq!(share.get_macs().len(), N_PARTIES - 1);
615        assert_eq!(share.get_keys().len(), N_PARTIES - 1);
616
617        // Generate a share with a specific value
618        let value = &Value::random(&mut rng);
619        let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
620        assert_eq!(share_with_value.get_value(), value);
621        assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
622        assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
623    }
624
625    #[test]
626    fn test_random_vec_and_reconstruct() {
627        let mut rng = random::test_rng();
628
629        // Generate a vector of random shares, one per party
630        let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
631        assert_eq!(shares.len(), N_PARTIES);
632        for share in &shares {
633            assert_eq!(share.get_macs().len(), N_PARTIES - 1);
634            assert_eq!(share.get_keys().len(), N_PARTIES - 1);
635        }
636        let unauthenticated_shares = shares
637            .iter()
638            .map(|s| s.get_value().to_owned())
639            .collect::<Vec<_>>();
640        let expected = Value::from_additive_shares(&unauthenticated_shares);
641        let reconstructed = Share::reconstruct_all(&shares).unwrap();
642        assert_eq!(reconstructed, expected);
643
644        // Secret share a value among n parties
645        let value = &Value::random(&mut rng);
646        let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
647        assert_eq!(shares.len(), N_PARTIES);
648        for share in &shares {
649            assert_eq!(share.get_macs().len(), N_PARTIES - 1);
650            assert_eq!(share.get_keys().len(), N_PARTIES - 1);
651        }
652        let reconstructed = Share::reconstruct_all(&shares).unwrap();
653        assert_eq!(reconstructed, value.to_owned());
654    }
655
656    #[test]
657    fn test_random_vec_with_global_key_and_reconstruct() {
658        let mut rng = random::test_rng();
659
660        // Generate n authenticated shares from n global keys (alphas)
661        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
662        let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
663        assert_eq!(shares_from_alphas.len(), N_PARTIES);
664        for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
665            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
666            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
667            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
668        }
669        let _ = Share::reconstruct_all(&shares_from_alphas).unwrap(); // Verify all MACs
670
671        // Generate n authenticated shares from a value and n global keys (alphas)
672        let value = &Value::random(&mut rng);
673        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
674        let shares_from_value_and_alphas: Vec<_> =
675            Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
676        assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
677        for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
678            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
679            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
680            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
681        }
682        let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
683        assert_eq!(&reconstructed, value);
684
685        // Generate n authenticated shares from n unauthenticated shares and n global keys (alphas)
686        let value = Value::random(&mut rng);
687        let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
688        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
689        let shares_from_unauth_and_alphas: Vec<_> =
690            Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
691        assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
692        for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
693            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
694            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
695            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
696        }
697        let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
698        assert_eq!(reconstructed, value);
699    }
700
701    #[test]
702    fn test_verify_mac() {
703        let mut rng = random::test_rng();
704
705        let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
706
707        // Verify each open separately
708        enumerate(shares.iter()).for_each(|(i, s_i)| {
709            enumerate(shares.iter())
710                .filter(|(j, _)| i != *j)
711                .for_each(|(j, s_j)| {
712                    let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
713                    s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
714                });
715        });
716
717        // Verify all openings at once
718        Share::verify_all(&shares).unwrap();
719    }
720
721    #[test]
722    fn test_add() {
723        let mut rng = random::test_rng();
724
725        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
726        let a = &Value::random(&mut rng);
727        let b = &Value::random(&mut rng);
728
729        let shares_a: Vec<_> =
730            Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
731        let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
732
733        // &a + &b
734        let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
735            .map(|(share_a, share_b)| share_a + share_b)
736            .collect::<Vec<_>>();
737        let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
738        assert_eq!(reconstructed, a + b);
739
740        // &a + b
741        let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
742            .map(|(share_a, share_b)| share_a + share_b)
743            .collect::<Vec<_>>();
744        let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
745        assert_eq!(reconstructed, a + b);
746
747        // a + &b
748        let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
749            .map(|(share_a, share_b)| share_a + share_b)
750            .collect::<Vec<_>>();
751        let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
752        assert_eq!(reconstructed, a + b);
753
754        // a + b
755        let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
756            .map(|(share_a, share_b)| share_a + share_b)
757            .collect::<Vec<_>>();
758        let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
759        assert_eq!(reconstructed, a + b);
760
761        // a += &b
762        let mut shares_a_add_assign_b_ref = shares_a.clone();
763        izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
764            .for_each(|(share_a, share_b)| *share_a += share_b);
765        let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
766        assert_eq!(reconstructed, a + b);
767
768        // a += b
769        let mut shares_a_add_assign_b = shares_a.clone();
770        izip_eq!(&mut shares_a_add_assign_b, shares_b)
771            .for_each(|(share_a, share_b)| *share_a += share_b);
772        let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
773        assert_eq!(reconstructed, a + b);
774    }
775
776    #[test]
777    fn test_add_secret() {
778        let mut rng = random::test_rng();
779
780        let a = &Value::random(&mut rng);
781        let k = &Constant::random(&mut rng);
782
783        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
784
785        // &a + k
786        let shares_a_plus_k_ref = enumerate(shares_a.iter())
787            .map(|(i, share_a)| share_a.add_plaintext(k, i == 0))
788            .collect::<Vec<_>>();
789        let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
790        assert_eq!(reconstructed, a + k);
791
792        // a + k
793        let shares_a_plus_k = enumerate(shares_a)
794            .map(|(i, share_a)| share_a.add_plaintext_owned(k, i == 0))
795            .collect::<Vec<_>>();
796        let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
797        assert_eq!(reconstructed, a + k);
798    }
799
800    #[test]
801    fn test_mul_constant() {
802        let mut rng = random::test_rng();
803
804        let a = &Value::random(&mut rng);
805        let k = &Constant::random(&mut rng);
806
807        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
808
809        // a * &k
810        let shares_a_times_k = izip_eq!(shares_a.clone())
811            .map(|share_a| share_a * k)
812            .collect::<Vec<_>>();
813        let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
814        assert_eq!(reconstructed, a * k);
815
816        // a *= &k
817        let mut shares_a_times_k_assign = shares_a.clone();
818        izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
819        let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
820        assert_eq!(reconstructed, a * k);
821    }
822
823    #[test]
824    fn test_sub() {
825        let mut rng = random::test_rng();
826        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
827
828        let a = &Value::random(&mut rng);
829        let b = &Value::random(&mut rng);
830
831        let shares_a: Vec<_> =
832            Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
833        let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
834
835        // &a - &b
836        let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
837            .map(|(share_a, share_b)| share_a - share_b)
838            .collect::<Vec<_>>();
839
840        let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
841        assert_eq!(reconstructed, a - b);
842
843        // &a - b
844        let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
845            .map(|(share_a, share_b)| share_a - share_b)
846            .collect::<Vec<_>>();
847        let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
848        assert_eq!(reconstructed, a - b);
849
850        // a - &b
851        let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
852            .map(|(share_a, share_b)| share_a - share_b)
853            .collect::<Vec<_>>();
854        let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
855        assert_eq!(reconstructed, a - b);
856
857        // a - b
858        let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
859            .map(|(share_a, share_b)| share_a - share_b)
860            .collect::<Vec<_>>();
861        let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
862        assert_eq!(reconstructed, a - b);
863
864        // a -= &b
865        let mut shares_a_sub_assign_b_ref = shares_a.clone();
866        izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
867            .for_each(|(share_a, share_b)| *share_a -= share_b);
868        let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
869        assert_eq!(reconstructed, a - b);
870
871        // a -= b
872        let mut shares_a_sub_assign_b = shares_a.clone();
873        izip_eq!(&mut shares_a_sub_assign_b, shares_b)
874            .for_each(|(share_a, share_b)| *share_a -= share_b);
875        let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
876        assert_eq!(reconstructed, a - b);
877    }
878
879    #[test]
880    fn test_neg() {
881        let mut rng = random::test_rng();
882
883        let a = Value::random(&mut rng);
884
885        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
886
887        // - &a
888        let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
889        let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
890        assert_eq!(reconstructed, -a.to_owned());
891
892        // - a
893        let shares_a_neg = shares_a
894            .into_iter()
895            .map(|share_a| -share_a)
896            .collect::<Vec<_>>();
897        let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
898        assert_eq!(reconstructed, -a.to_owned());
899    }
900
901    #[test]
902    fn test_conditional_select() {
903        let mut rng = random::test_rng();
904
905        let shares_a = Share::random_with(&mut rng, N_PARTIES);
906        let shares_b = Share::random_with(&mut rng, N_PARTIES);
907
908        // Select shares_a
909        let choice = Choice::from(0u8);
910        let selected = Share::conditional_select(&shares_a, &shares_b, choice);
911        assert_eq!(selected, shares_a);
912
913        // Select shares_b
914        let choice = Choice::from(1u8);
915        let selected = Share::conditional_select(&shares_a, &shares_b, choice);
916        assert_eq!(selected, shares_b);
917    }
918
919    #[test]
920    fn test_ct_eq() {
921        let mut rng = random::test_rng();
922
923        let shares_a = Share::random_with(&mut rng, N_PARTIES);
924        let shares_b = Share::random_with(&mut rng, N_PARTIES);
925
926        // Check equality
927        assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
928        assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
929        assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
930        assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
931    }
932}