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