primitives/sharing/authenticated/
field_share.rs

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