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#[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>, pub(crate) macs: Box<[FieldElement<F>]>, pub(crate) keys: Box<[FieldShareKey<F>]>, }
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 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 }
146}
147
148impl<F: FieldExtension> VerifiableWith for FieldShare<F> {
152 type VerificationData = ();
153
154 #[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 #[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
184impl<F: FieldExtension> Reconstructible for FieldShare<F> {
189 type Opening = OpenFieldShare<F>;
190 type Secret = SubfieldElement<F>;
191
192 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 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 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
228fn 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 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 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 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 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 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 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 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 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 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
425impl<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
484impl<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
504impl<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
564impl<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
584impl<'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
611impl<'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
622impl<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
650impl<F: FieldExtension> AddPlaintext for FieldShare<F> {
653 type AssociatedInformation = IsFirstPeer;
654 #[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 #[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
680impl<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 pub type Value = Scalar<C>;
722 pub type Constant = Scalar<C>;
723 pub type Share = ScalarShare<C>;
724 pub type GlobalKey = GlobalScalarKey<C>;
725 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 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 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 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 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 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(); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let choice = Choice::from(0u8);
1043 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1044 assert_eq!(selected, shares_a);
1045
1046 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 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}