primitives/sharing/authenticated/
field_share.rs

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