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