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#[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>, pub(crate) macs: Box<[FieldElement<F>]>, pub(crate) keys: Box<[FieldShareKey<F>]>, }
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 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 }
148}
149
150impl<F: FieldExtension> VerifiableWith for FieldShare<F> {
154 type VerificationData = ();
155
156 #[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 #[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
186impl<F: FieldExtension> Reconstructible for FieldShare<F> {
191 type Opening = OpenFieldShare<F>;
192 type Secret = SubfieldElement<F>;
193
194 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 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 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
230fn 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 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 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 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 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 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 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 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 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 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
427impl<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
486impl<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
506impl<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
566impl<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
586impl<'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
613impl<'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
624impl<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
652impl<F: FieldExtension> AddPlaintext for FieldShare<F> {
655 type AssociatedInformation = IsFirstPeer;
656 #[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 #[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
682impl<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 pub type Value = Scalar<C>;
724 pub type Constant = Scalar<C>;
725 pub type Share = ScalarShare<C>;
726 pub type GlobalKey = GlobalScalarKey<C>;
727 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 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 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 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 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 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(); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let choice = Choice::from(0u8);
1045 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1046 assert_eq!(selected, shares_a);
1047
1048 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 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}