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