primitives/sharing/authenticated/batched/
field_shares.rs

1use std::{
2    fmt::Debug,
3    iter::Sum as IterSum,
4    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use itertools::{enumerate, izip, Itertools};
8use serde::{Deserialize, Serialize};
9use subtle::{Choice, ConstantTimeEq};
10use typenum::{Prod, Sum, U1, U2, U3};
11
12use super::FieldShareKeys;
13use crate::{
14    algebra::{
15        field::{FieldExtension, SubfieldElement},
16        ops::transpose::transpose,
17    },
18    errors::{
19        PrimitiveError::{self},
20        VerificationError::MissingKey,
21    },
22    izip_eq,
23    random::{CryptoRngCore, Random, RandomWith},
24    sharing::{
25        authenticated::NParties,
26        unauthenticated::AdditiveShares,
27        FieldShare,
28        FieldShareKey,
29        GlobalFieldKey,
30        Reconstructible,
31        VerifiableWith,
32        VerificationError::MissingOpening,
33    },
34    types::{
35        heap_array::{FieldElements, SubfieldElements},
36        identifiers::PeerIndex,
37        ConditionallySelectable,
38        HeapArray,
39        Positive,
40    },
41    utils::IntoExactSizeIterator,
42};
43
44#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(bound = "F: FieldExtension, M: Positive")]
46pub struct OpenFieldShares<F: FieldExtension, M: Positive> {
47    pub(crate) value: SubfieldElements<F, M>,
48    pub(crate) mac: FieldElements<F, M>,
49}
50
51impl<F: FieldExtension, M: Positive> OpenFieldShares<F, M> {
52    pub fn new(value: SubfieldElements<F, M>, mac: FieldElements<F, M>) -> Self {
53        Self { value, mac }
54    }
55
56    pub fn get_value(&self) -> &SubfieldElements<F, M> {
57        &self.value
58    }
59
60    pub fn get_mac(&self) -> &FieldElements<F, M> {
61        &self.mac
62    }
63}
64
65impl<T: FieldExtension, M: Positive> Debug for OpenFieldShares<T, M> {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        f.debug_struct(format!("OpenFieldShares<{}>", M::USIZE).as_str())
68            .field("value", &self.value)
69            .field("mac", &self.mac)
70            .finish()
71    }
72}
73
74/// Authenticated share batch <x_i> of secret shared <x> held by `P_i` (this party).
75///
76/// They are composed of:
77/// - `x_i`, the unauthenticated share value (s.t. `x = Σ x_i`)
78/// - `{MAC(x_i)_j} ∀j∈[1..n]∖{i}`, the MACs of `x_i` for each of the other n-1 parties.
79/// - `{β_ij} ∀j∈[1..n]∖{i}` and `{α_ij} ∀j∈[1..n]∖{i}`, the (local and global) keys tied to the
80///   value&MACs of the other n-1 parties.
81///
82/// The authenticated shares fulfill this relation:
83///
84/// ```MAC(x_i)_j = α_ji · x_i + β_ji  ∀i∈[1..n]  ∀j∈[1..n]∖{i}```
85///     
86/// where `β_ji` and `α_ji` are the (local and global) keys of x_i held by P_j.
87#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
88#[serde(bound = "F: FieldExtension, M: Positive")]
89pub struct FieldShares<F, M>
90where
91    F: FieldExtension,
92    M: Positive, // # shares in the batch
93{
94    /// x_i
95    pub(crate) value: SubfieldElements<F, M>,
96    /// {MAC_1(x_i), ..., MAC_{i-1}(x_i), MAC_{i+1}(x_i), ..., MAC_n(x_i)}
97    pub(crate) macs: Box<[FieldElements<F, M>]>,
98    /// {(α_i1, β_i1), ..., (α_i{i-1}, β_i{i-1}), (α_i{i+1}, β_i{i+1}), ..., (α_in, β_in)}
99    pub(crate) keys: Box<[FieldShareKeys<F, M>]>,
100}
101
102impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
103    pub fn try_new(
104        value: SubfieldElements<F, M>,
105        macs: Box<[FieldElements<F, M>]>,
106        keys: Box<[FieldShareKeys<F, M>]>,
107    ) -> Result<Self, PrimitiveError> {
108        if macs.is_empty() {
109            return Err(PrimitiveError::InvalidParameters(
110                "n_parties < 2".to_string(),
111            ));
112        }
113        if macs.len() != keys.len() {
114            return Err(PrimitiveError::SizeError(macs.len(), keys.len()));
115        }
116        /* NOTE: We assume length equality for macs & keys from this point on */
117        Ok(Self { value, macs, keys })
118    }
119
120    fn new(
121        value: SubfieldElements<F, M>,
122        macs: Box<[FieldElements<F, M>]>,
123        keys: Box<[FieldShareKeys<F, M>]>,
124    ) -> Self {
125        Self { value, macs, keys }
126    }
127
128    pub fn get_value(&self) -> &SubfieldElements<F, M> {
129        &self.value
130    }
131
132    pub fn get_value_mut(&mut self) -> &mut SubfieldElements<F, M> {
133        &mut self.value
134    }
135
136    #[inline]
137    pub fn value(self) -> SubfieldElements<F, M> {
138        self.value
139    }
140
141    pub fn get_keys(&self) -> &[FieldShareKeys<F, M>] {
142        &self.keys
143    }
144
145    pub fn get_keys_mut(&mut self) -> &mut [FieldShareKeys<F, M>] {
146        &mut self.keys
147    }
148
149    pub fn get_key(&self, peer: PeerIndex) -> Option<&FieldShareKeys<F, M>> {
150        self.keys.get(peer)
151    }
152
153    pub fn get_macs(&self) -> &[FieldElements<F, M>] {
154        &self.macs
155    }
156
157    pub fn get_mac(&self, index: PeerIndex) -> Option<&FieldElements<F, M>> {
158        self.macs.get(index)
159    }
160
161    pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalFieldKey<F>> + '_ {
162        self.keys.iter().map(|key| key.get_alpha())
163    }
164
165    pub fn n_parties(&self) -> usize {
166        self.get_macs().len() + 1 // +1 for the local share
167    }
168}
169
170// --------------------
171// |   Verification   |
172// --------------------
173impl<F: FieldExtension, M: Positive> VerifiableWith for FieldShares<F, M> {
174    type VerificationData = ();
175    /// Check the MACs of the share received from another peer.
176    #[inline]
177    fn verify_from_peer_with(
178        &self,
179        open_share: &OpenFieldShares<F, M>,
180        from_peer: PeerIndex,
181        _verification_data: (),
182    ) -> Result<(), PrimitiveError> {
183        self.get_key(from_peer)
184            .ok_or(MissingKey(from_peer))?
185            .verify_mac(open_share)
186            .map_err(|e| e.blame(from_peer).add_state(self))
187    }
188
189    /// Check the MACs of each share received from all other peers.
190    #[inline]
191    fn verify_with(
192        &self,
193        open_shares: &[OpenFieldShares<F, M>],
194        _verification_data: (),
195    ) -> Result<(), PrimitiveError> {
196        izip_eq!(open_shares, &self.keys).enumerate().try_for_each(
197            |(from_peer, (open_share, key))| {
198                key.verify_mac(open_share)
199                    .map_err(|e| e.blame(from_peer).add_state(self))
200            },
201        )
202    }
203}
204
205// --------------------------------
206// |   Opening & Reconstruction   |
207// --------------------------------
208
209impl<F: FieldExtension, M: Positive> Reconstructible for FieldShares<F, M> {
210    type Opening = OpenFieldShares<F, M>;
211    type Secret = SubfieldElements<F, M>;
212
213    /// Open the share towards another peer.
214    fn open_to(&self, for_peer: PeerIndex) -> Result<OpenFieldShares<F, M>, PrimitiveError> {
215        let mac = self
216            .get_mac(for_peer)
217            .ok_or(MissingOpening(for_peer))?
218            .to_owned();
219        Ok(OpenFieldShares::new(self.get_value().to_owned(), mac))
220    }
221
222    /// Open the share towards all other peers.
223    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenFieldShares<F, M>> {
224        self.get_macs()
225            .iter()
226            .map(|mac| OpenFieldShares::new(self.get_value().to_owned(), mac.to_owned()))
227    }
228
229    /// Reconstruct a secret from openings coming from all other parties.
230    fn reconstruct(
231        &self,
232        openings: &[OpenFieldShares<F, M>],
233    ) -> Result<Self::Secret, PrimitiveError> {
234        if openings.len() != self.get_keys().len() {
235            return Err(PrimitiveError::SizeError(
236                openings.len(),
237                self.get_keys().len(),
238            ));
239        }
240
241        izip_eq!(openings, self.get_keys()).enumerate().try_fold(
242            self.get_value().to_owned(),
243            |acc, (i, (open_share, key))| {
244                key.verify_mac(open_share)
245                    .map_err(|e| e.blame(i).add_state(self))?;
246                Ok(acc + open_share.get_value())
247            },
248        )
249    }
250}
251
252// -------------------------
253// |   Random Generation   |
254// -------------------------
255
256fn compute_macs<F: FieldExtension, M: Positive>(
257    all_unauth_shares: &[SubfieldElements<F, M>],
258    all_keys: &[Box<[FieldShareKeys<F, M>]>],
259) -> Vec<Box<[FieldElements<F, M>]>> {
260    let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
261    enumerate(all_unauth_shares.iter())
262        .map(|(i, my_unauth_share)| {
263            enumerate(all_key_iters.iter_mut())
264                .filter(|(j, _)| *j != i)
265                .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
266                .collect()
267        })
268        .collect()
269}
270
271impl<F: FieldExtension, M: Positive> Random for FieldShares<F, M> {
272    fn random(_rng: impl CryptoRngCore) -> Self {
273        unimplemented!(
274            "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
275            std::any::type_name::<Self>()
276        )
277    }
278
279    /// Generate a random field share, with Macs and keys for all the other parties.
280    fn random_n<Container: FromIterator<Self>>(
281        mut rng: impl CryptoRngCore,
282        n_parties: NParties,
283    ) -> Container {
284        let all_unauth_shares: Vec<_> = SubfieldElements::random_n(&mut rng, n_parties);
285        let all_keys = (0..n_parties)
286            .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
287            .collect::<Vec<_>>();
288        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
289        izip_eq!(all_unauth_shares, all_macs, all_keys)
290            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
291            .collect()
292    }
293}
294
295impl<F: FieldExtension, M: Positive> RandomWith<NParties> for FieldShares<F, M> {
296    /// Generate a random field share, with Macs and keys for all the other parties.
297    fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
298        FieldShares::new(
299            SubfieldElements::<F, M>::random(&mut rng),
300            FieldElements::<F, M>::random_n(&mut rng, n_parties - 1),
301            FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1),
302        )
303    }
304}
305
306impl<F: FieldExtension, M: Positive> RandomWith<(NParties, SubfieldElements<F, M>)>
307    for FieldShares<F, M>
308{
309    /// Generate a random field share with a specific secret share as value and random macs & keys.
310    fn random_with(
311        mut rng: impl CryptoRngCore,
312        n_parties_value: (NParties, SubfieldElements<F, M>),
313    ) -> Self {
314        let (n_parties, value) = n_parties_value;
315        FieldShares::new(
316            value,
317            FieldElements::<F, M>::random_n(&mut rng, n_parties - 1),
318            FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1),
319        )
320    }
321}
322
323impl<F: FieldExtension, M: Positive> RandomWith<SubfieldElements<F, M>> for FieldShares<F, M> {
324    fn random_with(_rng: impl CryptoRngCore, _data: SubfieldElements<F, M>) -> Self {
325        unimplemented!(
326            "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
327            std::any::type_name::<Self>()
328        )
329    }
330
331    /// Secret share a value among n parties, generating an authenticated share for each
332    /// peer with consistent MACs and keys across all peers.
333    fn random_n_with<Container: FromIterator<Self>>(
334        mut rng: impl CryptoRngCore,
335        n_parties: usize,
336        value: SubfieldElements<F, M>,
337    ) -> Container {
338        let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
339        let all_keys = (0..n_parties)
340            .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
341            .collect::<Vec<_>>();
342        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
343        izip_eq!(all_unauth_shares, all_macs, all_keys)
344            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
345            .collect()
346    }
347
348    /// Generate an authenticated share given for each peer given its additve share
349    ///  with consistent MACs and keys across all peers.
350    fn random_n_with_each<Container: FromIterator<Self>>(
351        mut rng: impl CryptoRngCore,
352        unauth_shares: impl IntoExactSizeIterator<Item = SubfieldElements<F, M>>,
353    ) -> Container {
354        let all_unauth_shares = unauth_shares.into_iter().collect::<Vec<_>>();
355        let n_parties = all_unauth_shares.len();
356        let all_keys = (0..n_parties)
357            .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
358            .collect::<Vec<_>>();
359        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
360        izip_eq!(all_unauth_shares, all_macs, all_keys)
361            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
362            .collect()
363    }
364}
365
366impl<F: FieldExtension, M: Positive> RandomWith<Vec<GlobalFieldKey<F>>> for FieldShares<F, M> {
367    /// Generate a random field share from its global keys (alphas).
368    fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
369        let n_other_parties = alphas.len();
370        FieldShares::new(
371            SubfieldElements::random(&mut rng),
372            FieldElements::<F, M>::random_n(&mut rng, n_other_parties),
373            FieldShareKeys::<F, M>::random_n_with_each(&mut rng, alphas),
374        )
375    }
376
377    /// Generate one random field share per peer from their global keys (alphas).
378    fn random_n_with_each<Container: FromIterator<Self>>(
379        mut rng: impl CryptoRngCore,
380        all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
381    ) -> Container {
382        let all_alphas = all_alphas.into_iter();
383        let all_unauth_shares: Vec<_> = SubfieldElements::random_n(&mut rng, all_alphas.len());
384        let all_keys = all_alphas
385            .into_iter()
386            .map(|my_alphas| FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas))
387            .collect::<Vec<_>>();
388        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
389        izip_eq!(all_unauth_shares, all_macs, all_keys)
390            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
391            .collect()
392    }
393}
394
395impl<F: FieldExtension, M: Positive> RandomWith<(SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>)>
396    for FieldShares<F, M>
397{
398    /// Generate a random field share from its global keys (alphas) and its share
399    fn random_with(
400        mut rng: impl CryptoRngCore,
401        value_alphas: (SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>),
402    ) -> Self {
403        let (value, alphas) = value_alphas;
404        let n_other_parties = alphas.len();
405        FieldShares::new(
406            value,
407            FieldElements::<F, M>::random_n(&mut rng, n_other_parties),
408            FieldShareKeys::<F, M>::random_n_with_each(&mut rng, alphas),
409        )
410    }
411
412    /// Generate one random field share per peer from their global keys (alphas).
413    fn random_n_with_each<Container: FromIterator<Self>>(
414        mut rng: impl CryptoRngCore,
415        unauth_shares_and_alphas: impl IntoIterator<
416            Item = (SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>),
417        >,
418    ) -> Container {
419        let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
420            .into_iter()
421            .map(|(value, my_alphas)| {
422                (
423                    value,
424                    FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas),
425                )
426            })
427            .unzip();
428        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
429        izip_eq!(all_unauth_shares, all_macs, all_keys)
430            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
431            .collect()
432    }
433}
434
435impl<F: FieldExtension, M: Positive>
436    RandomWith<(SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>)> for FieldShares<F, M>
437{
438    fn random_with(
439        _rng: impl CryptoRngCore,
440        _data: (SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>),
441    ) -> Self {
442        unimplemented!(
443            "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
444        );
445    }
446
447    /// Generate a random field share per peer from a value to secret share and global keys
448    /// (alphas).
449    fn random_n_with<Container: FromIterator<Self>>(
450        mut rng: impl CryptoRngCore,
451        n_parties: usize,
452        secret_value_and_alphas: (SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>),
453    ) -> Container {
454        let (secret_value, all_alphas) = secret_value_and_alphas;
455        assert_eq!(
456            all_alphas.len(),
457            n_parties,
458            "Number of alphas must match the number of parties"
459        );
460        let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
461        let all_keys = all_alphas
462            .into_iter()
463            .map(|my_alphas| FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas))
464            .collect::<Vec<_>>();
465        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
466        izip_eq!(all_unauth_shares, all_macs, all_keys)
467            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
468            .collect()
469    }
470}
471
472// --------------
473// | Arithmetic |
474// --------------
475
476// === Addition === //
477
478impl<F: FieldExtension, M: Positive> Add for FieldShares<F, M> {
479    type Output = FieldShares<F, M>;
480
481    #[inline]
482    fn add(mut self, other: FieldShares<F, M>) -> Self::Output {
483        self.value += other.value;
484        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
485        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
486        self
487    }
488}
489
490impl<F: FieldExtension, M: Positive> Add<FieldShares<F, M>> for &FieldShares<F, M> {
491    type Output = FieldShares<F, M>;
492
493    #[inline]
494    fn add(self, mut other: FieldShares<F, M>) -> Self::Output {
495        other.value += &self.value;
496        izip_eq!(&mut other.macs, &self.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
497        izip_eq!(&mut other.keys, &self.keys).for_each(|(key_i, key_j)| *key_i += key_j);
498        other
499    }
500}
501
502impl<'a, F: FieldExtension, M: Positive> Add<&'a FieldShares<F, M>> for FieldShares<F, M> {
503    type Output = FieldShares<F, M>;
504
505    #[inline]
506    fn add(mut self, other: &'a FieldShares<F, M>) -> Self::Output {
507        self.value += &other.value;
508        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
509        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
510        self
511    }
512}
513
514impl<'a, F: FieldExtension, M: Positive> Add<&'a FieldShares<F, M>> for &FieldShares<F, M> {
515    type Output = FieldShares<F, M>;
516
517    #[inline]
518    fn add(self, other: &'a FieldShares<F, M>) -> Self::Output {
519        let mut res = self.clone();
520        res.value += &other.value;
521        izip_eq!(&mut res.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
522        izip_eq!(&mut res.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
523        res
524    }
525}
526
527// === AddAssign === //
528
529impl<F: FieldExtension, M: Positive> AddAssign for FieldShares<F, M> {
530    #[inline]
531    fn add_assign(&mut self, other: Self) {
532        self.value += other.value;
533        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
534        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
535    }
536}
537
538impl<'a, F: FieldExtension, M: Positive> AddAssign<&'a FieldShares<F, M>> for FieldShares<F, M> {
539    #[inline]
540    fn add_assign(&mut self, other: &'a FieldShares<F, M>) {
541        self.value += &other.value;
542        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
543        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
544    }
545}
546
547// === Subtraction === //
548
549impl<F: FieldExtension, M: Positive> Sub for FieldShares<F, M> {
550    type Output = FieldShares<F, M>;
551
552    #[inline]
553    fn sub(mut self, other: FieldShares<F, M>) -> Self::Output {
554        self.value -= other.value;
555        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
556        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
557        self
558    }
559}
560
561impl<'a, F: FieldExtension, M: Positive> Sub<&'a FieldShares<F, M>> for FieldShares<F, M> {
562    type Output = FieldShares<F, M>;
563
564    #[inline]
565    fn sub(mut self, other: &'a FieldShares<F, M>) -> Self::Output {
566        self.value -= &other.value;
567        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
568        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
569        self
570    }
571}
572
573impl<'a, F: FieldExtension, M: Positive> Sub<&'a FieldShares<F, M>> for &FieldShares<F, M> {
574    type Output = FieldShares<F, M>;
575
576    #[inline]
577    fn sub(self, other: &'a FieldShares<F, M>) -> Self::Output {
578        FieldShares {
579            value: &self.value - &other.value,
580            macs: izip_eq!(&self.macs, &other.macs)
581                .map(|(mac_i, mac_j)| mac_i - mac_j)
582                .collect(),
583            keys: izip_eq!(&self.keys, &other.keys)
584                .map(|(key_i, key_j)| key_i - key_j)
585                .collect(),
586        }
587    }
588}
589
590impl<F: FieldExtension, M: Positive> Sub<FieldShares<F, M>> for &FieldShares<F, M> {
591    type Output = FieldShares<F, M>;
592
593    #[inline]
594    fn sub(self, other: FieldShares<F, M>) -> Self::Output {
595        FieldShares {
596            value: &self.value - &other.value,
597            macs: izip_eq!(&self.macs, &other.macs)
598                .map(|(mac_i, mac_j)| mac_i - mac_j)
599                .collect(),
600            keys: izip_eq!(&self.keys, &other.keys)
601                .map(|(key_i, key_j)| key_i - key_j)
602                .collect(),
603        }
604    }
605}
606
607// === SubAssign === //
608
609impl<F: FieldExtension, M: Positive> SubAssign for FieldShares<F, M> {
610    #[inline]
611    fn sub_assign(&mut self, other: Self) {
612        self.value -= other.value;
613        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
614        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
615    }
616}
617
618impl<'a, F: FieldExtension, M: Positive> SubAssign<&'a FieldShares<F, M>> for FieldShares<F, M> {
619    #[inline]
620    fn sub_assign(&mut self, other: &'a FieldShares<F, M>) {
621        self.value -= &other.value;
622        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
623        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
624    }
625}
626
627// === Value multiplication === //
628
629impl<F: FieldExtension, M: Positive> Mul<SubfieldElement<F>> for FieldShares<F, M> {
630    type Output = FieldShares<F, M>;
631
632    #[inline]
633    fn mul(mut self, other: SubfieldElement<F>) -> FieldShares<F, M> {
634        self.value *= other;
635        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
636        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
637        self
638    }
639}
640
641impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElement<F>> for FieldShares<F, M> {
642    type Output = FieldShares<F, M>;
643
644    #[inline]
645    fn mul(mut self, other: &'a SubfieldElement<F>) -> FieldShares<F, M> {
646        self.value *= other;
647        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
648        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
649        self
650    }
651}
652
653impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for FieldShares<F, M> {
654    type Output = FieldShares<F, M>;
655
656    #[inline]
657    fn mul(mut self, other: &'a SubfieldElements<F, M>) -> FieldShares<F, M> {
658        self.value *= other;
659        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
660        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
661        self
662    }
663}
664
665impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for &FieldShares<F, M> {
666    type Output = FieldShares<F, M>;
667
668    #[inline]
669    fn mul(self, other: &'a SubfieldElements<F, M>) -> FieldShares<F, M> {
670        self.clone() * other
671    }
672}
673
674impl<F: FieldExtension, M: Positive> Mul<SubfieldElements<F, M>> for &FieldShares<F, M> {
675    type Output = FieldShares<F, M>;
676
677    #[inline]
678    fn mul(self, other: SubfieldElements<F, M>) -> FieldShares<F, M> {
679        self.clone() * &other
680    }
681}
682
683// === MulAssign === //
684
685impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElement<F>> for FieldShares<F, M> {
686    #[inline]
687    fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
688        self.value *= other;
689        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
690        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
691    }
692}
693
694impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElements<F, M>>
695    for FieldShares<F, M>
696{
697    #[inline]
698    fn mul_assign(&mut self, other: &'a SubfieldElements<F, M>) {
699        self.value *= other;
700        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
701        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
702    }
703}
704
705// === Negation === //
706
707impl<F: FieldExtension, M: Positive> Neg for FieldShares<F, M> {
708    type Output = Self;
709
710    #[inline]
711    fn neg(self) -> Self::Output {
712        FieldShares {
713            value: -self.value,
714            macs: izip_eq!(&self.macs).map(|mac_i| -mac_i).collect(),
715            keys: izip_eq!(&self.keys).map(|key_i| -key_i).collect(),
716        }
717    }
718}
719
720impl<F: FieldExtension, M: Positive> Neg for &FieldShares<F, M> {
721    type Output = FieldShares<F, M>;
722
723    #[inline]
724    fn neg(self) -> Self::Output {
725        FieldShares {
726            value: -&self.value,
727            macs: izip_eq!(&self.macs).map(|mac_i| -mac_i).collect(),
728            keys: izip_eq!(&self.keys).map(|key_i| -key_i).collect(),
729        }
730    }
731}
732
733// === Sum === //
734
735impl<F: FieldExtension, M: Positive> IterSum for FieldShares<F, M> {
736    fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
737        let first = iter.next().unwrap_or_default();
738        iter.fold(first, |acc, x| acc + x)
739    }
740}
741
742// === Constant addition / subtraction === //
743
744impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
745    /// Adds a public constant to the secret shared value, updating the keys accordingly.
746    /// A designated peer (P_0) will modify its value, while the other peers will update their keys.
747    #[inline]
748    pub fn add_secret_owned(
749        mut self,
750        constant: &SubfieldElements<F, M>,
751        is_peer_zero: bool,
752    ) -> Self {
753        if is_peer_zero {
754            self.value += constant;
755        } else {
756            let key0 = self.keys.get_mut(0).expect("Missing key 0");
757            key0.betas -= constant.clone() * *key0.alpha;
758        }
759        self
760    }
761
762    /// Adds a public constant to the secret shared value, updating the keys accordingly.
763    /// A designated peer (P_0) will modify its value, while the other peers will update their keys.
764    #[inline]
765    pub fn add_secret(&self, constant: &SubfieldElements<F, M>, is_peer_zero: bool) -> Self {
766        let result = self.clone();
767        result.add_secret_owned(constant, is_peer_zero)
768    }
769
770    /// Subtracts a public constant batch from the secret shared batch, updating the keys
771    /// accordingly. A designated peer (P_0) will modify its value, while the other peers will
772    /// update their keys.
773    #[inline]
774    pub fn sub_constant_array_owned(
775        mut self,
776        arr: &SubfieldElements<F, M>,
777        is_peer_zero: bool,
778    ) -> Self {
779        if is_peer_zero {
780            self.value -= arr;
781        } else {
782            let key0 = self.keys.get_mut(0).expect("Missing key 0");
783            let alpha = *key0.alpha;
784            izip_eq!(&mut key0.betas, arr).for_each(|(beta, val)| *beta += alpha * val);
785        }
786        self
787    }
788}
789
790// === Constant Time Selection / Equality === //
791
792impl<F: FieldExtension, M: Positive> ConditionallySelectable for FieldShares<F, M> {
793    #[inline]
794    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
795        FieldShares {
796            value: HeapArray::conditional_select(&a.value, &b.value, choice),
797            macs: izip_eq!(&a.macs, &b.macs)
798                .map(|(a_mac, b_mac)| HeapArray::conditional_select(a_mac, b_mac, choice))
799                .collect::<Vec<_>>()
800                .into(),
801            keys: izip_eq!(&a.keys, &b.keys)
802                .map(|(a_key, b_key)| FieldShareKeys::conditional_select(a_key, b_key, choice))
803                .collect::<Vec<_>>()
804                .into(),
805        }
806    }
807}
808
809impl<F: FieldExtension, M: Positive> ConstantTimeEq for FieldShares<F, M> {
810    #[inline]
811    fn ct_eq(&self, other: &Self) -> Choice {
812        self.value.ct_eq(&other.value) & self.keys.ct_eq(&other.keys) & self.macs.ct_eq(&other.macs)
813    }
814}
815
816// === Other Ops === //
817
818impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
819    /// Compute the dot product of the share value with another share.
820    pub fn dot_product(&self, other: &SubfieldElements<F, M>) -> FieldShare<F> {
821        FieldShare {
822            value: izip_eq!(&self.value, other)
823                .map(|(value_i, other_i)| *value_i * other_i)
824                .sum(),
825            macs: izip_eq!(&self.macs)
826                .map(|mac_i| {
827                    izip_eq!(mac_i, other)
828                        .map(|(mac_ij, other_i)| *mac_ij * other_i)
829                        .sum()
830                })
831                .collect(),
832            keys: izip_eq!(&self.keys)
833                .map(|key_i| {
834                    let beta = izip_eq!(&key_i.betas, other)
835                        .map(|(key_ij, other_i)| key_ij * other_i)
836                        .sum();
837                    FieldShareKey {
838                        alpha: key_i.alpha.clone(),
839                        beta,
840                    }
841                })
842                .collect(),
843        }
844    }
845}
846
847// -----------------------
848// |   Split and Merge   |
849// -----------------------
850
851impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
852    // Split the shares into two sets of shares with M1 and M2 shares respectively.
853    pub fn split<M1, M2>(self) -> (FieldShares<F, M1>, FieldShares<F, M2>)
854    where
855        M1: Positive,
856        M2: Positive + Add<M1, Output = M>,
857    {
858        let FieldShares { value, macs, keys } = self;
859
860        let (value1, value2) = value.split::<M1, M2>();
861        let (macs1, macs2): (Vec<_>, Vec<_>) = macs
862            .into_vec()
863            .into_iter()
864            .map(|mac| mac.split::<M1, M2>())
865            .collect();
866
867        let (keys1, keys2): (Vec<_>, Vec<_>) = keys
868            .into_vec()
869            .into_iter()
870            .map(|key| key.split::<M1, M2>())
871            .collect();
872
873        (
874            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
875            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
876        )
877    }
878
879    // Split the shares into two sets of shares with M/2 shares each.
880    pub fn split_halves<MDiv2>(self) -> (FieldShares<F, MDiv2>, FieldShares<F, MDiv2>)
881    where
882        MDiv2: Positive + Mul<U2, Output = M>,
883    {
884        let FieldShares { value, macs, keys } = self;
885
886        let (value1, value2) = value.split_halves::<MDiv2>();
887        let (macs1, macs2): (Vec<_>, Vec<_>) = macs
888            .into_vec()
889            .into_iter()
890            .map(|mac| mac.split_halves::<MDiv2>())
891            .collect();
892
893        let (keys1, keys2): (Vec<_>, Vec<_>) = keys
894            .into_vec()
895            .into_iter()
896            .map(|key| key.split_halves::<MDiv2>())
897            .collect();
898
899        (
900            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
901            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
902        )
903    }
904
905    // Merge two sets of shares with M/2 shares each into a single set of shares with M shares.
906    pub fn merge_halves(this: Self, other: Self) -> FieldShares<F, Prod<M, U2>>
907    where
908        M: Positive + Mul<U2, Output: Positive>,
909    {
910        let FieldShares { value, macs, keys } = this;
911        let FieldShares {
912            value: other_value,
913            macs: other_macs,
914            keys: other_keys,
915        } = other;
916
917        let value = SubfieldElements::merge_halves(value, other_value);
918        let macs = izip_eq!(macs, other_macs)
919            .map(|(mac, other_mac)| FieldElements::merge_halves(mac, other_mac))
920            .collect::<Vec<_>>();
921        let keys = izip_eq!(keys, other_keys)
922            .map(|(key, other_key)| FieldShareKeys::merge_halves(key, other_key))
923            .collect::<Vec<_>>();
924
925        FieldShares::try_new(value, macs.into(), keys.into()).unwrap()
926    }
927
928    // Split the shares into three sets of shares with M1, M2 and M3 shares respectively.
929    pub fn split3<M1, M2, M3>(self) -> (FieldShares<F, M1>, FieldShares<F, M2>, FieldShares<F, M3>)
930    where
931        M1: Positive,
932        M2: Positive + Add<M1>,
933        M3: Positive + Add<Sum<M2, M1>, Output = M>,
934    {
935        let FieldShares { value, macs, keys } = self;
936
937        let (value1, value2, value3) = value.split3::<M1, M2, M3>();
938        let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
939            .into_vec()
940            .into_iter()
941            .map(|mac| mac.split3::<M1, M2, M3>())
942            .multiunzip();
943
944        let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
945            .into_vec()
946            .into_iter()
947            .map(|key| key.split3::<M1, M2, M3>())
948            .multiunzip();
949
950        (
951            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
952            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
953            FieldShares::try_new(value3, macs3.into(), keys3.into()).unwrap(),
954        )
955    }
956
957    // Split the shares into three sets of shares with M/3 shares each.
958    pub fn split_thirds<MDiv3>(
959        self,
960    ) -> (
961        FieldShares<F, MDiv3>,
962        FieldShares<F, MDiv3>,
963        FieldShares<F, MDiv3>,
964    )
965    where
966        MDiv3: Positive + Mul<U3, Output = M>,
967    {
968        let FieldShares { value, macs, keys } = self;
969
970        let (value1, value2, value3) = value.split_thirds::<MDiv3>();
971        let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
972            .into_vec()
973            .into_iter()
974            .map(|mac| mac.split_thirds::<MDiv3>())
975            .multiunzip();
976
977        let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
978            .into_vec()
979            .into_iter()
980            .map(|key| key.split_thirds::<MDiv3>())
981            .multiunzip();
982
983        (
984            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
985            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
986            FieldShares::try_new(value3, macs3.into(), keys3.into()).unwrap(),
987        )
988    }
989
990    // Merge three sets of shares with M/3 shares each into a single set of shares with M shares.
991    pub fn merge_thirds(this: Self, other1: Self, other2: Self) -> FieldShares<F, Prod<M, U3>>
992    where
993        M: Positive + Mul<U3, Output: Positive>,
994    {
995        let FieldShares {
996            value: v1,
997            macs: m1,
998            keys: k1,
999        } = this;
1000        let FieldShares {
1001            value: v2,
1002            macs: m2,
1003            keys: k2,
1004        } = other1;
1005        let FieldShares {
1006            value: v3,
1007            macs: m3,
1008            keys: k3,
1009        } = other2;
1010
1011        let value = SubfieldElements::merge_thirds(v1, v2, v3);
1012        let macs = izip_eq!(m1, m2, m3)
1013            .map(|(mac1, mac2, mac3)| FieldElements::merge_thirds(mac1, mac2, mac3))
1014            .collect::<Vec<_>>();
1015        let keys = izip_eq!(k1, k2, k3)
1016            .map(|(key1, key2, key3)| FieldShareKeys::merge_thirds(key1, key2, key3))
1017            .collect::<Vec<_>>();
1018
1019        FieldShares::try_new(value, macs.into(), keys.into()).unwrap()
1020    }
1021}
1022
1023// ------------------------
1024// |   Iterate and Cast   |
1025// ------------------------
1026
1027// === Single Element === //
1028
1029impl<F: FieldExtension> From<FieldShare<F>> for FieldShares<F, U1> {
1030    fn from(share: FieldShare<F>) -> Self {
1031        FieldShares {
1032            value: HeapArray::from(share.value),
1033            macs: share
1034                .macs
1035                .into_vec()
1036                .into_iter()
1037                .map(HeapArray::from)
1038                .collect(),
1039            keys: share
1040                .keys
1041                .into_vec()
1042                .into_iter()
1043                .map(FieldShareKeys::from)
1044                .collect(),
1045        }
1046    }
1047}
1048
1049// === Multiple elements === //
1050
1051impl<F: FieldExtension, M: Positive> From<HeapArray<FieldShare<F>, M>> for FieldShares<F, M> {
1052    fn from(shares: HeapArray<FieldShare<F>, M>) -> Self {
1053        let (values, macs, keys): (Vec<_>, Vec<_>, Vec<_>) = shares
1054            .into_iter()
1055            .map(|share| (share.value, share.macs, share.keys))
1056            .multiunzip();
1057        let macs = transpose(macs)
1058            .into_iter()
1059            .map(HeapArray::from_iter)
1060            .collect::<Box<[_]>>();
1061        let keys = transpose(keys)
1062            .into_iter()
1063            .map(|peer_keys| {
1064                let alpha = peer_keys[0].get_alpha();
1065                let betas = peer_keys
1066                    .into_iter()
1067                    .map(|key| {
1068                        let FieldShareKey { alpha: _, beta } = key;
1069                        beta
1070                    })
1071                    .collect::<HeapArray<_, M>>();
1072                FieldShareKeys::new(alpha, betas)
1073            })
1074            .collect::<Box<[_]>>();
1075
1076        FieldShares {
1077            value: HeapArray::from_iter(values),
1078            macs,
1079            keys,
1080        }
1081    }
1082}
1083
1084// === Iterators === //
1085
1086type SubfieldElementsIterator<F, M> = <SubfieldElements<F, M> as IntoIterator>::IntoIter;
1087type FieldElementsIterator<F, M> = <FieldElements<F, M> as IntoIterator>::IntoIter;
1088
1089#[derive(Default, Clone, Debug)]
1090pub struct FieldSharesIterator<F: FieldExtension, M: Positive> {
1091    index: usize,
1092
1093    value: SubfieldElementsIterator<F, M>,
1094    macs: Vec<FieldElementsIterator<F, M>>,
1095    betas: Vec<FieldElementsIterator<F, M>>,
1096    alphas: Vec<GlobalFieldKey<F>>,
1097}
1098
1099impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldSharesIterator<F, M> {
1100    fn len(&self) -> usize {
1101        M::to_usize() - self.index
1102    }
1103}
1104
1105impl<F: FieldExtension, M: Positive> Iterator for FieldSharesIterator<F, M> {
1106    type Item = FieldShare<F>;
1107
1108    fn next(&mut self) -> Option<Self::Item> {
1109        if self.index < M::to_usize() {
1110            let value = self.value.next()?;
1111            let macs = self
1112                .macs
1113                .iter_mut()
1114                .map(|mac| mac.next())
1115                .collect::<Option<_>>()?;
1116            let keys = izip!(&mut self.betas, &self.alphas)
1117                .map(|(beta, alpha)| {
1118                    beta.next().map(|beta| FieldShareKey {
1119                        alpha: alpha.clone(),
1120                        beta,
1121                    })
1122                })
1123                .collect::<Option<_>>()?;
1124            self.index += 1;
1125            Some(FieldShare::new(value, macs, keys))
1126        } else {
1127            None
1128        }
1129    }
1130}
1131
1132impl<F: FieldExtension, M: Positive> IntoIterator for FieldShares<F, M> {
1133    type Item = FieldShare<F>;
1134    type IntoIter = FieldSharesIterator<F, M>;
1135
1136    fn into_iter(self) -> Self::IntoIter {
1137        let FieldShares { value, macs, keys } = self;
1138        let value = value.into_iter();
1139        let macs = macs
1140            .into_vec()
1141            .into_iter()
1142            .map(|mac| mac.into_iter())
1143            .collect();
1144        let (betas, alphas): (Vec<_>, Vec<_>) = keys
1145            .into_vec()
1146            .into_iter()
1147            .map(|key| (key.betas.into_iter(), key.alpha))
1148            .unzip();
1149
1150        FieldSharesIterator {
1151            index: 0,
1152            value,
1153            macs,
1154            betas,
1155            alphas,
1156        }
1157    }
1158}
1159
1160#[cfg(test)]
1161mod tests {
1162    use std::ops::Div;
1163
1164    use itertools::enumerate;
1165    use typenum::{Unsigned, U12};
1166
1167    use super::*;
1168    use crate::{
1169        algebra::elliptic_curve::Curve25519Ristretto as C,
1170        random::{self},
1171        sharing::{GlobalScalarKey, ScalarShares, Verifiable},
1172        types::heap_array::curve_arrays::Scalars,
1173    };
1174
1175    // TODO: Generalize once PairwiseAuthenticatedShare trait is implemented.
1176
1177    //////////////////////////////////////////////////
1178    // CHANGE ONLY THESE TO TEST ANOTHER SHARE TYPE //
1179    pub type M = U12;
1180    pub type Value = Scalars<C, M>;
1181    pub type Constant = Scalars<C, M>;
1182    pub type Share = ScalarShares<C, M>;
1183    pub type GlobalKey = GlobalScalarKey<C>;
1184
1185    // Batching
1186    pub type Mdiv2 = <M as Div<U2>>::Output;
1187    pub type ShareMdiv2 = ScalarShares<C, Mdiv2>;
1188    pub type Mdiv3 = <M as Div<U3>>::Output;
1189    pub type ShareMdiv3 = ScalarShares<C, Mdiv3>;
1190    //////////////////////////////////////////////////
1191
1192    pub const N_PARTIES: usize = 3;
1193
1194    #[test]
1195    fn test_open_to() {
1196        let mut rng = random::test_rng();
1197        let local_share = Share::random_with(&mut rng, N_PARTIES);
1198
1199        for i in 0..N_PARTIES - 1 {
1200            let open_share = local_share.open_to(i).unwrap();
1201            assert_eq!(open_share.get_value(), &local_share.value);
1202            assert_eq!(open_share.get_mac(), &local_share.macs[i]);
1203        }
1204    }
1205
1206    #[test]
1207    fn test_random() {
1208        let mut rng = random::test_rng();
1209
1210        // Generate a completely random share
1211        let share = Share::random_with(&mut rng, N_PARTIES);
1212        assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1213        assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1214
1215        // Generate a share with a specific value
1216        let value = &Value::random(&mut rng);
1217        let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
1218        assert_eq!(share_with_value.get_value(), value);
1219        assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
1220        assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
1221    }
1222
1223    #[test]
1224    fn test_random_vec_and_reconstruct() {
1225        let mut rng = random::test_rng();
1226
1227        // Generate a vector of random shares, one per party
1228        let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
1229        assert_eq!(shares.len(), N_PARTIES);
1230        for share in &shares {
1231            assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1232            assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1233        }
1234        let unauthenticated_shares = shares
1235            .iter()
1236            .map(|s| s.get_value().to_owned())
1237            .collect::<Vec<_>>();
1238        let expected = Value::from_additive_shares(&unauthenticated_shares);
1239        let reconstructed = Share::reconstruct_all(&shares).unwrap();
1240        assert_eq!(reconstructed, expected);
1241
1242        // Secret share a value among n parties
1243        let value = &Value::random(&mut rng);
1244        let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
1245        assert_eq!(shares.len(), N_PARTIES);
1246        for share in &shares {
1247            assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1248            assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1249        }
1250        let reconstructed = Share::reconstruct_all(&shares).unwrap();
1251        assert_eq!(reconstructed, value.to_owned());
1252    }
1253
1254    #[test]
1255    fn test_random_vec_with_global_key_and_reconstruct() {
1256        let mut rng = random::test_rng();
1257
1258        // Generate n authenticated shares from n global keys (alphas)
1259        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1260        let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
1261        assert_eq!(shares_from_alphas.len(), N_PARTIES);
1262        for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
1263            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1264            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1265            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1266        }
1267        let _ = Share::reconstruct_all(&shares_from_alphas).unwrap(); // Verify all MACs
1268
1269        // Generate n authenticated shares from a value and n global keys (alphas)
1270        let value = &Value::random(&mut rng);
1271        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1272        let shares_from_value_and_alphas: Vec<_> =
1273            Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
1274        assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
1275        for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
1276            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1277            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1278            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1279        }
1280        let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
1281        assert_eq!(&reconstructed, value);
1282
1283        // Generate n authenticated shares from n unauthenticated shares and n global keys (alphas)
1284        let value = Value::random(&mut rng);
1285        let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
1286        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1287        let shares_from_unauth_and_alphas: Vec<_> =
1288            Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
1289        assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
1290        for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
1291            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1292            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1293            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1294        }
1295        let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
1296        assert_eq!(reconstructed, value);
1297    }
1298
1299    #[test]
1300    fn test_verify_mac() {
1301        let mut rng = random::test_rng();
1302
1303        let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
1304
1305        // Verify each open separately
1306        enumerate(shares.iter()).for_each(|(i, s_i)| {
1307            enumerate(shares.iter())
1308                .filter(|(j, _)| i != *j)
1309                .for_each(|(j, s_j)| {
1310                    let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
1311                    s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
1312                });
1313        });
1314
1315        // Verify all openings at once
1316        Share::verify_all(&shares).unwrap();
1317    }
1318
1319    #[test]
1320    fn test_add() {
1321        let mut rng = random::test_rng();
1322
1323        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1324        let a = &Value::random(&mut rng);
1325        let b = &Value::random(&mut rng);
1326
1327        let shares_a: Vec<_> =
1328            Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1329        let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1330
1331        // &a + &b
1332        let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
1333            .map(|(share_a, share_b)| share_a + share_b)
1334            .collect::<Vec<_>>();
1335        let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
1336        assert_eq!(reconstructed, a + b);
1337
1338        // &a + b
1339        let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
1340            .map(|(share_a, share_b)| share_a + share_b)
1341            .collect::<Vec<_>>();
1342        let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
1343        assert_eq!(reconstructed, a + b);
1344
1345        // a + &b
1346        let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1347            .map(|(share_a, share_b)| share_a + share_b)
1348            .collect::<Vec<_>>();
1349        let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
1350        assert_eq!(reconstructed, a + b);
1351
1352        // a + b
1353        let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1354            .map(|(share_a, share_b)| share_a + share_b)
1355            .collect::<Vec<_>>();
1356        let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
1357        assert_eq!(reconstructed, a + b);
1358
1359        // a += &b
1360        let mut shares_a_add_assign_b_ref = shares_a.clone();
1361        izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
1362            .for_each(|(share_a, share_b)| *share_a += share_b);
1363        let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
1364        assert_eq!(reconstructed, a + b);
1365
1366        // a += b
1367        let mut shares_a_add_assign_b = shares_a.clone();
1368        izip_eq!(&mut shares_a_add_assign_b, shares_b)
1369            .for_each(|(share_a, share_b)| *share_a += share_b);
1370        let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
1371        assert_eq!(reconstructed, a + b);
1372    }
1373
1374    #[test]
1375    fn test_add_secret() {
1376        let mut rng = random::test_rng();
1377
1378        let a = &Value::random(&mut rng);
1379        let k = &Value::random(&mut rng);
1380
1381        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1382
1383        // &a + k
1384        let shares_a_plus_k_ref = enumerate(shares_a.iter())
1385            .map(|(i, share_a)| share_a.add_secret(k, i == 0))
1386            .collect::<Vec<_>>();
1387        let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
1388        assert_eq!(reconstructed, a + k);
1389
1390        // a + k
1391        let shares_a_plus_k = enumerate(shares_a)
1392            .map(|(i, share_a)| share_a.add_secret_owned(k, i == 0))
1393            .collect::<Vec<_>>();
1394        let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
1395        assert_eq!(reconstructed, a + k);
1396    }
1397
1398    #[test]
1399    fn test_mul_constant() {
1400        let mut rng = random::test_rng();
1401
1402        let a = &Value::random(&mut rng);
1403        let k = &Constant::random(&mut rng);
1404
1405        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1406
1407        // &a * k
1408        let shares_a_times_k_ref = izip_eq!(&shares_a)
1409            .map(|share_a| share_a * k.to_owned())
1410            .collect::<Vec<_>>();
1411        let reconstructed = Share::reconstruct_all(&shares_a_times_k_ref).unwrap();
1412        assert_eq!(reconstructed, a.to_owned() * k);
1413
1414        // a * k
1415        let shares_a_times_k = izip_eq!(shares_a.clone())
1416            .map(|share_a| share_a * k)
1417            .collect::<Vec<_>>();
1418        let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
1419        assert_eq!(reconstructed, a * k);
1420
1421        // a *= k
1422        let mut shares_a_times_k_assign = shares_a.clone();
1423        izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
1424        let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
1425        assert_eq!(reconstructed, a * k);
1426    }
1427
1428    #[test]
1429    fn test_sub() {
1430        let mut rng = random::test_rng();
1431        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1432
1433        let a = &Value::random(&mut rng);
1434        let b = &Value::random(&mut rng);
1435
1436        let shares_a: Vec<_> =
1437            Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1438        let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1439
1440        // &a - &b
1441        let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
1442            .map(|(share_a, share_b)| share_a - share_b)
1443            .collect::<Vec<_>>();
1444
1445        let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
1446        assert_eq!(reconstructed, a - b);
1447
1448        // &a - b
1449        let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
1450            .map(|(share_a, share_b)| share_a - share_b)
1451            .collect::<Vec<_>>();
1452        let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
1453        assert_eq!(reconstructed, a - b);
1454
1455        // a - &b
1456        let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1457            .map(|(share_a, share_b)| share_a - share_b)
1458            .collect::<Vec<_>>();
1459        let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
1460        assert_eq!(reconstructed, a - b);
1461
1462        // a - b
1463        let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1464            .map(|(share_a, share_b)| share_a - share_b)
1465            .collect::<Vec<_>>();
1466        let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
1467        assert_eq!(reconstructed, a - b);
1468
1469        // a -= &b
1470        let mut shares_a_sub_assign_b_ref = shares_a.clone();
1471        izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
1472            .for_each(|(share_a, share_b)| *share_a -= share_b);
1473        let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
1474        assert_eq!(reconstructed, a - b);
1475
1476        // a -= b
1477        let mut shares_a_sub_assign_b = shares_a.clone();
1478        izip_eq!(&mut shares_a_sub_assign_b, shares_b)
1479            .for_each(|(share_a, share_b)| *share_a -= share_b);
1480        let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
1481        assert_eq!(reconstructed, a - b);
1482    }
1483
1484    #[test]
1485    fn test_neg() {
1486        let mut rng = random::test_rng();
1487
1488        let a = Value::random(&mut rng);
1489
1490        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1491
1492        // - &a
1493        let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
1494        let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
1495        assert_eq!(reconstructed, -a.to_owned());
1496
1497        // - a
1498        let shares_a_neg = shares_a
1499            .into_iter()
1500            .map(|share_a| -share_a)
1501            .collect::<Vec<_>>();
1502        let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
1503        assert_eq!(reconstructed, -a.to_owned());
1504    }
1505
1506    #[test]
1507    fn test_conditional_select() {
1508        let mut rng = random::test_rng();
1509
1510        let shares_a = Share::random_with(&mut rng, N_PARTIES);
1511        let shares_b = Share::random_with(&mut rng, N_PARTIES);
1512
1513        // Select shares_a
1514        let choice = Choice::from(0u8);
1515        let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1516        assert_eq!(selected, shares_a);
1517
1518        // Select shares_b
1519        let choice = Choice::from(1u8);
1520        let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1521        assert_eq!(selected, shares_b);
1522    }
1523
1524    #[test]
1525    fn test_ct_eq() {
1526        let mut rng = random::test_rng();
1527
1528        let shares_a = Share::random_with(&mut rng, N_PARTIES);
1529        let shares_b = Share::random_with(&mut rng, N_PARTIES);
1530
1531        // Check equality
1532        assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
1533        assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
1534        assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
1535        assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
1536    }
1537
1538    #[test]
1539    fn test_split_halves() {
1540        let m_div2 = Mdiv2::to_usize();
1541
1542        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1543
1544        let (shares1, shares2) = shares.clone().split_halves::<Mdiv2>();
1545
1546        // Check that the shares are split correctly
1547        assert_eq!(shares1.get_value().len(), m_div2);
1548        assert_eq!(shares2.get_value().len(), m_div2);
1549
1550        assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
1551        assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
1552
1553        izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
1554            assert_eq!(mac1.as_ref(), &mac[..m_div2]);
1555            assert_eq!(mac2.as_ref(), &mac[m_div2..]);
1556        });
1557        izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
1558            assert_eq!(key1.alpha, key.alpha);
1559            assert_eq!(key2.alpha, key.alpha);
1560            assert_eq!(key1.betas.as_ref(), &key.betas[..m_div2]);
1561            assert_eq!(key2.betas.as_ref(), &key.betas[m_div2..]);
1562        });
1563
1564        // Check that the shares can be merged back
1565        let merged_shares = ShareMdiv2::merge_halves(shares1, shares2);
1566        assert_eq!(merged_shares, shares);
1567    }
1568
1569    #[test]
1570    fn test_split_thirds() {
1571        let m_div3 = Mdiv3::to_usize();
1572
1573        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1574
1575        let (shares1, shares2, shares3) = shares.clone().split_thirds::<Mdiv3>();
1576
1577        // Check that the shares are split correctly
1578        assert_eq!(shares1.get_value().len(), m_div3);
1579        assert_eq!(shares2.get_value().len(), m_div3);
1580        assert_eq!(shares3.get_value().len(), m_div3);
1581
1582        assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
1583        assert_eq!(
1584            shares2.get_value().as_ref(),
1585            &shares.get_value()[m_div3..(2 * m_div3)]
1586        );
1587        assert_eq!(
1588            shares3.get_value().as_ref(),
1589            &shares.get_value()[(2 * m_div3)..]
1590        );
1591
1592        izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
1593            |(mac1, mac2, mac3, mac)| {
1594                assert_eq!(mac1.as_ref(), &mac[..m_div3]);
1595                assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
1596                assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
1597            },
1598        );
1599
1600        izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
1601            |(key1, key2, key3, key)| {
1602                assert_eq!(key1.alpha, key.alpha);
1603                assert_eq!(key2.alpha, key.alpha);
1604                assert_eq!(key3.alpha, key.alpha);
1605
1606                assert_eq!(key1.betas.as_ref(), &key.betas[..m_div3]);
1607                assert_eq!(key2.betas.as_ref(), &key.betas[m_div3..(2 * m_div3)]);
1608                assert_eq!(key3.betas.as_ref(), &key.betas[(2 * m_div3)..(3 * m_div3)]);
1609            },
1610        );
1611
1612        // Check that the shares can be merged back
1613        let merged_shares = ShareMdiv3::merge_thirds(shares1, shares2, shares3);
1614        assert_eq!(merged_shares, shares);
1615    }
1616
1617    #[test]
1618    fn test_into_iter() {
1619        let m = M::to_usize();
1620
1621        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1622
1623        let mut iter = shares.clone().into_iter();
1624        assert_eq!(iter.len(), m);
1625
1626        for i in 0..m {
1627            assert_eq!(iter.len(), m - i);
1628            let share = iter.next().unwrap();
1629            assert_eq!(share.value, shares.get_value()[i]);
1630
1631            for j in 0..N_PARTIES - 1 {
1632                assert_eq!(share.macs[j], shares.macs[j][i]);
1633                assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
1634                assert_eq!(share.keys[j].beta, shares.keys[j].betas[i]);
1635            }
1636        }
1637    }
1638}