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