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::{CollectAll, 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::MinimumLength(2, 0));
78 }
79 if macs.len() != keys.len() {
80 return Err(PrimitiveError::InvalidSize(keys.len(), macs.len()));
81 }
82 Ok(Self { value, macs, keys })
84 }
85
86 pub(super) fn new(
87 value: SubfieldElement<F>,
88 macs: Box<[FieldElement<F>]>,
89 keys: Box<[FieldShareKey<F>]>,
90 ) -> Self {
91 Self { value, macs, keys }
92 }
93
94 pub fn zero_from_alphas(alphas: impl ExactSizeIterator<Item = GlobalFieldKey<F>>) -> Self {
95 let n_peers = alphas.len();
96 FieldShare {
97 value: SubfieldElement::zero(),
98 macs: vec![FieldElement::<F>::zero(); n_peers].into_boxed_slice(),
99 keys: alphas
100 .map(|alpha| FieldShareKey::<F>::new(alpha, FieldElement::zero()))
101 .collect(),
102 }
103 }
104
105 #[inline]
106 pub fn get_value(&self) -> &SubfieldElement<F> {
107 &self.value
108 }
109
110 #[inline]
111 pub fn value(self) -> SubfieldElement<F> {
112 self.value
113 }
114
115 #[inline]
116 pub fn get_macs(&self) -> &[FieldElement<F>] {
117 &self.macs
118 }
119
120 #[inline]
121 pub fn get_mac(&self, peer_index: PeerIndex) -> Option<&FieldElement<F>> {
122 self.macs.get(peer_index)
123 }
124
125 #[inline]
126 pub fn get_keys(&self) -> &[FieldShareKey<F>] {
127 &self.keys
128 }
129
130 #[inline]
131 pub fn get_key(&self, peer_index: PeerIndex) -> Option<&FieldShareKey<F>> {
132 self.keys.get(peer_index)
133 }
134
135 #[inline]
136 pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalFieldKey<F>> + '_ {
137 self.keys.iter().map(|key| key.get_alpha())
138 }
139
140 #[inline]
141 pub fn n_parties(&self) -> usize {
142 self.macs.len() + 1 }
144}
145
146impl<F: FieldExtension> VerifiableWith for FieldShare<F> {
150 type VerificationData = ();
151
152 #[inline]
154 fn verify_from_peer_with(
155 &self,
156 open_share: &OpenFieldShare<F>,
157 peer: PeerIndex,
158 _verification_data: (),
159 ) -> Result<(), PrimitiveError> {
160 self.get_key(peer)
161 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?
162 .verify_mac(open_share)
163 .map_err(|e| e.blame(peer))
164 }
165
166 #[inline]
168 fn verify_with(
169 &self,
170 open_shares: &[OpenFieldShare<F>],
171 _verification_data: (),
172 ) -> Result<(), PrimitiveError> {
173 enumerate(izip_eq!(open_shares, &self.keys))
174 .map(|(from_peer, (open_share, key))| {
175 key.verify_mac(open_share).map_err(|e| e.blame(from_peer))
176 })
177 .collect_errors()?;
178 Ok(())
179 }
180}
181
182impl<F: FieldExtension> Reconstructible for FieldShare<F> {
187 type Opening = OpenFieldShare<F>;
188 type Secret = SubfieldElement<F>;
189
190 fn open_to(&self, peer: PeerIndex) -> Result<OpenFieldShare<F>, PrimitiveError> {
192 let mac = self
193 .get_mac(peer)
194 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.macs.len()))?
195 .to_owned();
196 Ok(OpenFieldShare::new(self.get_value().to_owned(), mac))
197 }
198
199 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenFieldShare<F>> {
201 self.get_macs()
202 .iter()
203 .map(|mac| OpenFieldShare::new(self.get_value().to_owned(), mac.to_owned()))
204 }
205
206 fn reconstruct(&self, openings: &[OpenFieldShare<F>]) -> Result<Self::Secret, PrimitiveError> {
208 if openings.len() != self.get_keys().len() {
209 return Err(PrimitiveError::InvalidSize(
210 self.get_keys().len(),
211 openings.len(),
212 ));
213 }
214 self.verify_with(openings, ())?;
215 Ok(openings
216 .iter()
217 .fold(self.get_value().to_owned(), |acc, open_share| {
218 acc + open_share.get_value()
219 }))
220 }
221}
222
223fn compute_macs<F: FieldExtension>(
228 all_unauth_shares: &[SubfieldElement<F>],
229 all_keys: &[Box<[FieldShareKey<F>]>],
230) -> Vec<Box<[FieldElement<F>]>> {
231 let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
232 enumerate(all_unauth_shares.iter())
233 .map(|(i, my_unauth_share)| {
234 enumerate(all_key_iters.iter_mut())
235 .filter(|(j, _)| *j != i)
236 .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
237 .collect()
238 })
239 .collect()
240}
241
242impl<F: FieldExtension> Random for FieldShare<F> {
243 fn random(_rng: impl CryptoRngCore) -> Self {
244 unimplemented!(
245 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
246 std::any::type_name::<Self>()
247 )
248 }
249
250 fn random_n<Container: FromIterator<Self>>(
252 mut rng: impl CryptoRngCore,
253 n_parties: usize,
254 ) -> Container {
255 let all_unauth_shares: Vec<_> = SubfieldElement::random_n(&mut rng, n_parties);
256 let all_keys = (0..n_parties)
257 .map(|_| FieldShareKey::<F>::random_n(&mut rng, n_parties - 1))
258 .collect::<Vec<_>>();
259 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
260 izip_eq!(all_unauth_shares, all_macs, all_keys)
261 .map(|(value, macs, keys)| FieldShare { value, macs, keys })
262 .collect()
263 }
264}
265
266impl<F: FieldExtension> RandomWith<NParties> for FieldShare<F> {
267 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
269 FieldShare {
270 value: SubfieldElement::random(&mut rng),
271 macs: FieldElement::<F>::random_n(&mut rng, n_parties - 1),
272 keys: FieldShareKey::<F>::random_n(&mut rng, n_parties - 1),
273 }
274 }
275}
276
277impl<F: FieldExtension> RandomWith<(NParties, SubfieldElement<F>)> for FieldShare<F> {
278 fn random_with(
280 mut rng: impl CryptoRngCore,
281 n_parties_and_value: (NParties, SubfieldElement<F>),
282 ) -> Self {
283 let (n_parties, value) = n_parties_and_value;
284 FieldShare {
285 value,
286 macs: FieldElement::<F>::random_n(&mut rng, n_parties - 1),
287 keys: FieldShareKey::<F>::random_n(&mut rng, n_parties - 1),
288 }
289 }
290}
291
292impl<F: FieldExtension> RandomWith<SubfieldElement<F>> for FieldShare<F> {
293 fn random_with(_rng: impl CryptoRngCore, _data: SubfieldElement<F>) -> Self {
294 unimplemented!(
295 "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
296 std::any::type_name::<Self>()
297 )
298 }
299
300 fn random_n_with<Container: FromIterator<Self>>(
303 mut rng: impl CryptoRngCore,
304 n_parties: usize,
305 value: SubfieldElement<F>,
306 ) -> Container {
307 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
308 let all_keys = (0..n_parties)
309 .map(|_| FieldShareKey::<F>::random_n(&mut rng, n_parties - 1))
310 .collect::<Vec<_>>();
311 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
312 izip_eq!(all_unauth_shares, all_macs, all_keys)
313 .map(|(value, macs, keys)| FieldShare { value, macs, keys })
314 .collect()
315 }
316}
317
318impl<F: FieldExtension> RandomWith<Vec<GlobalFieldKey<F>>> for FieldShare<F> {
319 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
321 let n_other_parties = alphas.len();
322 FieldShare {
323 value: SubfieldElement::random(&mut rng),
324 macs: FieldElement::<F>::random_n(&mut rng, n_other_parties),
325 keys: FieldShareKey::<F>::random_n_with_each(&mut rng, alphas),
326 }
327 }
328
329 fn random_n_with_each<Container: FromIterator<Self>>(
331 mut rng: impl CryptoRngCore,
332 all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
333 ) -> Container {
334 let all_alphas = all_alphas.into_iter();
335 let all_unauth_shares: Vec<_> = SubfieldElement::random_n(&mut rng, all_alphas.len());
336 let all_keys = all_alphas
337 .into_iter()
338 .map(|my_alphas| FieldShareKey::<F>::random_n_with_each(&mut rng, my_alphas))
339 .collect::<Vec<_>>();
340 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
341 izip_eq!(all_unauth_shares, all_macs, all_keys)
342 .map(|(value, macs, keys)| FieldShare { value, macs, keys })
343 .collect()
344 }
345}
346
347impl<F: FieldExtension> RandomWith<(SubfieldElement<F>, Vec<GlobalFieldKey<F>>)> for FieldShare<F> {
348 fn random_with(
350 mut rng: impl CryptoRngCore,
351 value_alphas: (SubfieldElement<F>, Vec<GlobalFieldKey<F>>),
352 ) -> Self {
353 let (value, alphas) = value_alphas;
354 let n_other_parties = alphas.len();
355 FieldShare {
356 value,
357 macs: FieldElement::<F>::random_n(&mut rng, n_other_parties),
358 keys: FieldShareKey::<F>::random_n_with_each(&mut rng, alphas),
359 }
360 }
361
362 fn random_n_with_each<Container: FromIterator<Self>>(
364 mut rng: impl CryptoRngCore,
365 unauth_shares_and_alphas: impl IntoExactSizeIterator<
366 Item = (SubfieldElement<F>, Vec<GlobalFieldKey<F>>),
367 >,
368 ) -> Container {
369 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
370 .into_iter()
371 .map(|(value, my_alphas)| {
372 (
373 value,
374 FieldShareKey::<F>::random_n_with_each(&mut rng, my_alphas),
375 )
376 })
377 .unzip();
378 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
379 izip_eq!(all_unauth_shares, all_macs, all_keys)
380 .map(|(value, macs, keys)| FieldShare { value, macs, keys })
381 .collect()
382 }
383}
384
385impl<F: FieldExtension> RandomWith<(SubfieldElement<F>, Vec<Vec<GlobalFieldKey<F>>>)>
386 for FieldShare<F>
387{
388 fn random_with(
389 _source: impl CryptoRngCore,
390 _data: (SubfieldElement<F>, Vec<Vec<GlobalFieldKey<F>>>),
391 ) -> Self {
392 unimplemented!(
393 "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
394 );
395 }
396
397 fn random_n_with<Container: FromIterator<Self>>(
400 mut rng: impl CryptoRngCore,
401 n_parties: usize,
402 (secret_value, all_alphas): (SubfieldElement<F>, Vec<Vec<GlobalFieldKey<F>>>),
403 ) -> Container {
404 if n_parties != all_alphas.len() {
405 panic!("n_parties does not match the number of alphas provided");
406 }
407
408 let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
409 let all_keys = all_alphas
410 .into_iter()
411 .map(|my_alphas| FieldShareKey::<F>::random_n_with_each(&mut rng, my_alphas))
412 .collect::<Vec<_>>();
413 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
414 izip_eq!(all_unauth_shares, all_macs, all_keys)
415 .map(|(value, macs, keys)| FieldShare { value, macs, keys })
416 .collect()
417 }
418}
419
420#[macros::op_variants(owned, borrowed, flipped_commutative)]
427impl<'a, F: FieldExtension> Add<&'a FieldShare<F>> for FieldShare<F> {
428 type Output = FieldShare<F>;
429
430 #[inline]
431 fn add(mut self, other: &'a FieldShare<F>) -> Self::Output {
432 self.value += &other.value;
433 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
434 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
435 self
436 }
437}
438
439#[macros::op_variants(owned)]
440impl<'a, F: FieldExtension> AddAssign<&'a FieldShare<F>> for FieldShare<F> {
441 #[inline]
442 fn add_assign(&mut self, other: &'a FieldShare<F>) {
443 self.value += &other.value;
444 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
445 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
446 }
447}
448
449#[macros::op_variants(owned, borrowed, flipped)]
452impl<'a, F: FieldExtension> Sub<&'a FieldShare<F>> for FieldShare<F> {
453 type Output = FieldShare<F>;
454
455 #[inline]
456 fn sub(mut self, other: &'a FieldShare<F>) -> Self::Output {
457 self.value -= &other.value;
458 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
459 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
460 self
461 }
462}
463
464#[macros::op_variants(owned)]
465impl<'a, F: FieldExtension> SubAssign<&'a FieldShare<F>> for FieldShare<F> {
466 #[inline]
467 fn sub_assign(&mut self, other: &'a FieldShare<F>) {
468 self.value -= &other.value;
469 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
470 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
471 }
472}
473
474#[macros::op_variants(owned, borrowed, flipped)]
477impl<'a, F: FieldExtension> Mul<&'a SubfieldElement<F>> for FieldShare<F> {
478 type Output = FieldShare<F>;
479
480 #[inline]
481 fn mul(mut self, other: &'a SubfieldElement<F>) -> FieldShare<F> {
482 self.value *= other;
483 izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
484 izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
485 self
486 }
487}
488
489#[macros::op_variants(owned)]
492impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for FieldShare<F> {
493 #[inline]
494 fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
495 self.value *= other;
496 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
497 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
498 }
499}
500
501#[macros::op_variants(borrowed)]
504impl<F: FieldExtension> Neg for FieldShare<F> {
505 type Output = FieldShare<F>;
506
507 #[inline]
508 fn neg(self) -> Self::Output {
509 FieldShare {
510 value: -self.value,
511 keys: self.keys.iter().map(|key| -key).collect(),
512 macs: self.macs.iter().map(|mac| -mac).collect(),
513 }
514 }
515}
516
517impl<F: FieldExtension> AddPlaintext for FieldShare<F> {
520 type AssociatedInformation = IsFirstPeer;
521 #[inline]
524 fn add_plaintext(&self, plaintext: &SubfieldElement<F>, is_peer_zero: IsFirstPeer) -> Self {
525 let result = self.clone();
526 result.add_plaintext_owned(plaintext, is_peer_zero)
527 }
528
529 #[inline]
532 fn add_plaintext_owned(
533 mut self,
534 plaintext: &SubfieldElement<F>,
535 is_peer_zero: IsFirstPeer,
536 ) -> Self {
537 if is_peer_zero {
538 self.value += plaintext;
539 } else {
540 let key0 = self.keys.get_mut(0).expect("Missing key 0");
541 key0.beta -= *key0.alpha * plaintext;
542 }
543 self
544 }
545}
546
547impl<F: FieldExtension> ConstantTimeEq for FieldShare<F> {
552 #[inline]
553 fn ct_eq(&self, other: &Self) -> Choice {
554 self.value.ct_eq(&other.value) & self.keys.ct_eq(&other.keys) & self.macs.ct_eq(&other.macs)
555 }
556}
557
558impl<F: FieldExtension> ConditionallySelectable for FieldShare<F> {
559 #[inline]
560 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
561 FieldShare {
562 value: SubfieldElement::conditional_select(&a.value, &b.value, choice),
563 macs: izip_eq!(&a.macs, &b.macs)
564 .map(|(a_mac, b_mac)| FieldElement::conditional_select(a_mac, b_mac, choice))
565 .collect(),
566 keys: izip_eq!(&a.keys, &b.keys)
567 .map(|(a_key, b_key)| FieldShareKey::conditional_select(a_key, b_key, choice))
568 .collect(),
569 }
570 }
571}
572
573#[cfg(test)]
574mod tests {
575 use itertools::enumerate;
576
577 use super::*;
578 use crate::{
579 algebra::elliptic_curve::{Curve25519Ristretto as C, Scalar},
580 random::{self},
581 sharing::{GlobalScalarKey, ScalarShare, Verifiable},
582 };
583
584 pub type Value = Scalar<C>;
589 pub type Constant = Scalar<C>;
590 pub type Share = ScalarShare<C>;
591 pub type GlobalKey = GlobalScalarKey<C>;
592 pub const N_PARTIES: usize = 3;
595
596 #[test]
597 fn test_open_to() {
598 let mut rng = random::test_rng();
599 let local_share = Share::random_with(&mut rng, N_PARTIES);
600
601 for i in 0..N_PARTIES - 1 {
602 let open_share = local_share.open_to(i).unwrap();
603 assert_eq!(open_share.get_value(), &local_share.value);
604 assert_eq!(open_share.get_mac(), &local_share.macs[i]);
605 }
606 }
607
608 #[test]
609 fn test_random() {
610 let mut rng = random::test_rng();
611
612 let share = Share::random_with(&mut rng, N_PARTIES);
614 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
615 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
616
617 let value = &Value::random(&mut rng);
619 let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
620 assert_eq!(share_with_value.get_value(), value);
621 assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
622 assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
623 }
624
625 #[test]
626 fn test_random_vec_and_reconstruct() {
627 let mut rng = random::test_rng();
628
629 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
631 assert_eq!(shares.len(), N_PARTIES);
632 for share in &shares {
633 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
634 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
635 }
636 let unauthenticated_shares = shares
637 .iter()
638 .map(|s| s.get_value().to_owned())
639 .collect::<Vec<_>>();
640 let expected = Value::from_additive_shares(&unauthenticated_shares);
641 let reconstructed = Share::reconstruct_all(&shares).unwrap();
642 assert_eq!(reconstructed, expected);
643
644 let value = &Value::random(&mut rng);
646 let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
647 assert_eq!(shares.len(), N_PARTIES);
648 for share in &shares {
649 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
650 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
651 }
652 let reconstructed = Share::reconstruct_all(&shares).unwrap();
653 assert_eq!(reconstructed, value.to_owned());
654 }
655
656 #[test]
657 fn test_random_vec_with_global_key_and_reconstruct() {
658 let mut rng = random::test_rng();
659
660 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
662 let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
663 assert_eq!(shares_from_alphas.len(), N_PARTIES);
664 for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
665 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
666 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
667 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
668 }
669 let _ = Share::reconstruct_all(&shares_from_alphas).unwrap(); let value = &Value::random(&mut rng);
673 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
674 let shares_from_value_and_alphas: Vec<_> =
675 Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
676 assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
677 for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
678 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
679 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
680 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
681 }
682 let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
683 assert_eq!(&reconstructed, value);
684
685 let value = Value::random(&mut rng);
687 let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
688 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
689 let shares_from_unauth_and_alphas: Vec<_> =
690 Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
691 assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
692 for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
693 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
694 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
695 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
696 }
697 let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
698 assert_eq!(reconstructed, value);
699 }
700
701 #[test]
702 fn test_verify_mac() {
703 let mut rng = random::test_rng();
704
705 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
706
707 enumerate(shares.iter()).for_each(|(i, s_i)| {
709 enumerate(shares.iter())
710 .filter(|(j, _)| i != *j)
711 .for_each(|(j, s_j)| {
712 let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
713 s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
714 });
715 });
716
717 Share::verify_all(&shares).unwrap();
719 }
720
721 #[test]
722 fn test_add() {
723 let mut rng = random::test_rng();
724
725 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
726 let a = &Value::random(&mut rng);
727 let b = &Value::random(&mut rng);
728
729 let shares_a: Vec<_> =
730 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
731 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
732
733 let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
735 .map(|(share_a, share_b)| share_a + share_b)
736 .collect::<Vec<_>>();
737 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
738 assert_eq!(reconstructed, a + b);
739
740 let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
742 .map(|(share_a, share_b)| share_a + share_b)
743 .collect::<Vec<_>>();
744 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
745 assert_eq!(reconstructed, a + b);
746
747 let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
749 .map(|(share_a, share_b)| share_a + share_b)
750 .collect::<Vec<_>>();
751 let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
752 assert_eq!(reconstructed, a + b);
753
754 let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
756 .map(|(share_a, share_b)| share_a + share_b)
757 .collect::<Vec<_>>();
758 let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
759 assert_eq!(reconstructed, a + b);
760
761 let mut shares_a_add_assign_b_ref = shares_a.clone();
763 izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
764 .for_each(|(share_a, share_b)| *share_a += share_b);
765 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
766 assert_eq!(reconstructed, a + b);
767
768 let mut shares_a_add_assign_b = shares_a.clone();
770 izip_eq!(&mut shares_a_add_assign_b, shares_b)
771 .for_each(|(share_a, share_b)| *share_a += share_b);
772 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
773 assert_eq!(reconstructed, a + b);
774 }
775
776 #[test]
777 fn test_add_secret() {
778 let mut rng = random::test_rng();
779
780 let a = &Value::random(&mut rng);
781 let k = &Constant::random(&mut rng);
782
783 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
784
785 let shares_a_plus_k_ref = enumerate(shares_a.iter())
787 .map(|(i, share_a)| share_a.add_plaintext(k, i == 0))
788 .collect::<Vec<_>>();
789 let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
790 assert_eq!(reconstructed, a + k);
791
792 let shares_a_plus_k = enumerate(shares_a)
794 .map(|(i, share_a)| share_a.add_plaintext_owned(k, i == 0))
795 .collect::<Vec<_>>();
796 let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
797 assert_eq!(reconstructed, a + k);
798 }
799
800 #[test]
801 fn test_mul_constant() {
802 let mut rng = random::test_rng();
803
804 let a = &Value::random(&mut rng);
805 let k = &Constant::random(&mut rng);
806
807 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
808
809 let shares_a_times_k = izip_eq!(shares_a.clone())
811 .map(|share_a| share_a * k)
812 .collect::<Vec<_>>();
813 let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
814 assert_eq!(reconstructed, a * k);
815
816 let mut shares_a_times_k_assign = shares_a.clone();
818 izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
819 let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
820 assert_eq!(reconstructed, a * k);
821 }
822
823 #[test]
824 fn test_sub() {
825 let mut rng = random::test_rng();
826 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
827
828 let a = &Value::random(&mut rng);
829 let b = &Value::random(&mut rng);
830
831 let shares_a: Vec<_> =
832 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
833 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
834
835 let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
837 .map(|(share_a, share_b)| share_a - share_b)
838 .collect::<Vec<_>>();
839
840 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
841 assert_eq!(reconstructed, a - b);
842
843 let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
845 .map(|(share_a, share_b)| share_a - share_b)
846 .collect::<Vec<_>>();
847 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
848 assert_eq!(reconstructed, a - b);
849
850 let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
852 .map(|(share_a, share_b)| share_a - share_b)
853 .collect::<Vec<_>>();
854 let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
855 assert_eq!(reconstructed, a - b);
856
857 let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
859 .map(|(share_a, share_b)| share_a - share_b)
860 .collect::<Vec<_>>();
861 let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
862 assert_eq!(reconstructed, a - b);
863
864 let mut shares_a_sub_assign_b_ref = shares_a.clone();
866 izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
867 .for_each(|(share_a, share_b)| *share_a -= share_b);
868 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
869 assert_eq!(reconstructed, a - b);
870
871 let mut shares_a_sub_assign_b = shares_a.clone();
873 izip_eq!(&mut shares_a_sub_assign_b, shares_b)
874 .for_each(|(share_a, share_b)| *share_a -= share_b);
875 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
876 assert_eq!(reconstructed, a - b);
877 }
878
879 #[test]
880 fn test_neg() {
881 let mut rng = random::test_rng();
882
883 let a = Value::random(&mut rng);
884
885 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
886
887 let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
889 let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
890 assert_eq!(reconstructed, -a.to_owned());
891
892 let shares_a_neg = shares_a
894 .into_iter()
895 .map(|share_a| -share_a)
896 .collect::<Vec<_>>();
897 let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
898 assert_eq!(reconstructed, -a.to_owned());
899 }
900
901 #[test]
902 fn test_conditional_select() {
903 let mut rng = random::test_rng();
904
905 let shares_a = Share::random_with(&mut rng, N_PARTIES);
906 let shares_b = Share::random_with(&mut rng, N_PARTIES);
907
908 let choice = Choice::from(0u8);
910 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
911 assert_eq!(selected, shares_a);
912
913 let choice = Choice::from(1u8);
915 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
916 assert_eq!(selected, shares_b);
917 }
918
919 #[test]
920 fn test_ct_eq() {
921 let mut rng = random::test_rng();
922
923 let shares_a = Share::random_with(&mut rng, N_PARTIES);
924 let shares_b = Share::random_with(&mut rng, N_PARTIES);
925
926 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
928 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
929 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
930 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
931 }
932}