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::GlobalCurveKey;
8use crate::{
9 algebra::elliptic_curve::{Curve, Point, Scalar, ScalarAsExtension},
10 errors::{PrimitiveError, VerificationError::MissingKey},
11 izip_eq,
12 random::{CryptoRngCore, Random, RandomWith},
13 sharing::{
14 authenticated::NParties,
15 unauthenticated::AdditiveShares,
16 AddPlaintext,
17 CurveKey,
18 GlobalFieldKey,
19 IsFirstPeer,
20 Reconstructible,
21 VerifiableWith,
22 VerificationError::MissingOpening,
23 },
24 types::{ConditionallySelectable, PeerIndex},
25 utils::IntoExactSizeIterator,
26};
27
28#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
29#[serde(bound = "C: Curve")]
30pub struct OpenPointShare<C: Curve> {
31 pub(crate) value: Point<C>,
32 pub(crate) mac: Point<C>,
33}
34
35impl<C: Curve> OpenPointShare<C> {
36 pub fn new(value: Point<C>, mac: Point<C>) -> Self {
37 Self { value, mac }
38 }
39
40 pub fn get_value(&self) -> &Point<C> {
41 &self.value
42 }
43
44 pub fn get_mac(&self) -> &Point<C> {
45 &self.mac
46 }
47}
48
49#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
52#[serde(bound = "C: Curve")]
53pub struct PointShare<C: Curve> {
54 pub(crate) value: Point<C>, pub(crate) macs: Box<[Point<C>]>, pub(crate) keys: Box<[CurveKey<C>]>, }
58
59impl<C: Curve> PointShare<C> {
60 pub fn try_new(
61 value: Point<C>,
62 macs: Box<[Point<C>]>,
63 keys: Box<[CurveKey<C>]>,
64 ) -> Result<Self, PrimitiveError> {
65 if macs.is_empty() {
66 return Err(PrimitiveError::InvalidParameters(
67 "n_parties < 2".to_string(),
68 ));
69 }
70 if macs.len() != keys.len() {
71 return Err(PrimitiveError::SizeError(macs.len(), keys.len()));
72 }
73 Ok(Self { value, macs, keys })
75 }
76
77 fn new(value: Point<C>, macs: Box<[Point<C>]>, keys: Box<[CurveKey<C>]>) -> Self {
78 Self { value, macs, keys }
79 }
80
81 pub fn zero_from_alphas(
82 alphas: impl ExactSizeIterator<Item = GlobalFieldKey<C::Scalar>>,
83 ) -> Self {
84 let n_peers = alphas.len();
85
86 let value = Point::identity();
87 let macs = vec![Point::<C>::identity(); n_peers].into_boxed_slice();
88 let keys = alphas
89 .map(|alpha| CurveKey::new(alpha, Point::identity()))
90 .collect();
91 PointShare::new(value, macs, keys)
92 }
93
94 pub fn get_value(&self) -> &Point<C> {
95 &self.value
96 }
97
98 #[inline]
99 pub fn value(self) -> Point<C> {
100 self.value
101 }
102
103 pub fn get_keys(&self) -> &[CurveKey<C>] {
104 &self.keys
105 }
106
107 pub fn get_key(&self, index: PeerIndex) -> Option<&CurveKey<C>> {
108 self.keys.get(index)
109 }
110
111 pub fn get_macs(&self) -> &[Point<C>] {
112 &self.macs
113 }
114
115 pub fn get_mac(&self, index: PeerIndex) -> Option<&Point<C>> {
116 self.macs.get(index)
117 }
118
119 #[inline]
120 pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalCurveKey<C>> + '_ {
121 self.keys.iter().map(|key| key.get_alpha())
122 }
123}
124
125impl<C: Curve> VerifiableWith for PointShare<C> {
129 type VerificationData = ();
130 #[inline]
132 fn verify_from_peer_with(
133 &self,
134 open_share: &OpenPointShare<C>,
135 from_peer: PeerIndex,
136 _verification_data: (),
137 ) -> Result<(), PrimitiveError> {
138 self.get_key(from_peer)
139 .ok_or(MissingKey(from_peer))?
140 .verify_mac(open_share)
141 .map_err(|e| e.blame(from_peer).add_state(self))
142 }
143
144 #[inline]
146 fn verify_with(
147 &self,
148 open_shares: &[OpenPointShare<C>],
149 _verification_data: (),
150 ) -> Result<(), PrimitiveError> {
151 izip_eq!(open_shares, &self.keys).enumerate().try_for_each(
152 |(from_peer, (open_share, key))| {
153 key.verify_mac(open_share)
154 .map_err(|e| e.blame(from_peer).add_state(self))
155 },
156 )
157 }
158}
159
160impl<C: Curve> Reconstructible for PointShare<C> {
165 type Opening = OpenPointShare<C>;
166 type Secret = Point<C>;
167
168 fn open_to(&self, for_peer: PeerIndex) -> Result<OpenPointShare<C>, PrimitiveError> {
170 let mac = self
171 .get_mac(for_peer)
172 .ok_or(MissingOpening(for_peer))?
173 .to_owned();
174 Ok(OpenPointShare::new(self.get_value().to_owned(), mac))
175 }
176
177 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenPointShare<C>> {
179 self.get_macs()
180 .iter()
181 .map(|mac| OpenPointShare::new(self.get_value().to_owned(), mac.to_owned()))
182 }
183
184 fn reconstruct(&self, openings: &[OpenPointShare<C>]) -> Result<Self::Secret, PrimitiveError> {
186 if openings.len() != self.get_keys().len() {
187 return Err(PrimitiveError::SizeError(
188 openings.len(),
189 self.get_keys().len(),
190 ));
191 }
192
193 izip_eq!(openings, self.get_keys()).enumerate().try_fold(
194 self.get_value().to_owned(),
195 |acc, (i, (open_share, key))| {
196 key.verify_mac(open_share)
197 .map_err(|e| e.blame(i).add_state(self))?;
198 Ok(acc + open_share.get_value())
199 },
200 )
201 }
202}
203
204fn compute_macs<C: Curve>(
209 all_unauth_shares: &[Point<C>],
210 all_keys: &[Box<[CurveKey<C>]>],
211) -> Vec<Box<[Point<C>]>> {
212 let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
213 enumerate(all_unauth_shares.iter())
214 .map(|(i, my_unauth_share)| {
215 enumerate(all_key_iters.iter_mut())
216 .filter(|(j, _)| *j != i)
217 .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
218 .collect()
219 })
220 .collect()
221}
222
223impl<C: Curve> Random for PointShare<C> {
224 fn random(_rng: impl CryptoRngCore) -> Self {
225 unimplemented!(
226 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
227 std::any::type_name::<Self>()
228 )
229 }
230
231 fn random_n<Container: FromIterator<Self>>(
233 mut rng: impl CryptoRngCore,
234 n_parties: NParties,
235 ) -> Container {
236 let all_unauth_shares: Vec<_> = Point::random_n(&mut rng, n_parties);
237 let all_keys = (0..n_parties)
238 .map(|_| CurveKey::<C>::random_n(&mut rng, n_parties - 1))
239 .collect::<Vec<_>>();
240 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
241 izip_eq!(all_unauth_shares, all_macs, all_keys)
242 .map(|(value, macs, keys)| PointShare { value, macs, keys })
243 .collect()
244 }
245}
246
247impl<C: Curve> RandomWith<NParties> for PointShare<C> {
248 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
250 PointShare {
251 value: Point::random(&mut rng),
252 macs: Point::<C>::random_n(&mut rng, n_parties - 1),
253 keys: CurveKey::<C>::random_n(&mut rng, n_parties - 1),
254 }
255 }
256}
257
258impl<C: Curve> RandomWith<(NParties, Point<C>)> for PointShare<C> {
259 fn random_with(mut rng: impl CryptoRngCore, n_parties_value: (NParties, Point<C>)) -> Self {
261 let (n_parties, value) = n_parties_value;
262 PointShare {
263 value,
264 macs: Point::<C>::random_n(&mut rng, n_parties - 1),
265 keys: CurveKey::<C>::random_n(&mut rng, n_parties - 1),
266 }
267 }
268}
269
270impl<C: Curve> RandomWith<Point<C>> for PointShare<C> {
271 fn random_with(_rng: impl CryptoRngCore, _data: Point<C>) -> Self {
272 unimplemented!(
273 "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
274 std::any::type_name::<Self>()
275 )
276 }
277
278 fn random_n_with<Container: FromIterator<Self>>(
281 mut rng: impl CryptoRngCore,
282 n_parties: NParties,
283 value: Point<C>,
284 ) -> Container {
285 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
286 let all_keys = (0..n_parties)
287 .map(|_| CurveKey::<C>::random_n(&mut rng, n_parties - 1))
288 .collect::<Vec<_>>();
289 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
290 izip_eq!(all_unauth_shares, all_macs, all_keys)
291 .map(|(value, macs, keys)| PointShare { value, macs, keys })
292 .collect()
293 }
294
295 fn random_n_with_each<Container: FromIterator<Self>>(
298 mut rng: impl CryptoRngCore,
299 all_unauth_shares: impl IntoExactSizeIterator<Item = Point<C>>,
300 ) -> Container {
301 let all_unauth_shares = all_unauth_shares.into_iter().collect::<Vec<_>>();
302 let n_parties = all_unauth_shares.len();
303 let all_keys = (0..n_parties)
304 .map(|_| CurveKey::<C>::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)| PointShare { value, macs, keys })
309 .collect()
310 }
311}
312
313impl<C: Curve> RandomWith<Vec<GlobalCurveKey<C>>> for PointShare<C> {
314 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalCurveKey<C>>) -> Self {
316 let n_other_parties = alphas.len();
317 PointShare {
318 value: Point::random(&mut rng),
319 macs: Point::<C>::random_n(&mut rng, n_other_parties),
320 keys: CurveKey::<C>::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<GlobalCurveKey<C>>>,
328 ) -> Container {
329 let all_alphas = all_alphas.into_iter();
330 let all_unauth_shares: Vec<_> = Point::random_n(&mut rng, all_alphas.len());
331 let all_keys = all_alphas
332 .into_iter()
333 .map(|my_alphas| CurveKey::<C>::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)| PointShare { value, macs, keys })
338 .collect()
339 }
340}
341
342impl<C: Curve> RandomWith<(Point<C>, Vec<GlobalCurveKey<C>>)> for PointShare<C> {
343 fn random_with(
345 mut rng: impl CryptoRngCore,
346 value_alphas: (Point<C>, Vec<GlobalCurveKey<C>>),
347 ) -> Self {
348 let (value, alphas) = value_alphas;
349 let n_other_parties = alphas.len();
350 PointShare {
351 value,
352 macs: Point::<C>::random_n(&mut rng, n_other_parties),
353 keys: CurveKey::<C>::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 IntoIterator<Item = (Point<C>, Vec<GlobalCurveKey<C>>)>,
361 ) -> Container {
362 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
363 .into_iter()
364 .map(|(value, my_alphas)| {
365 (
366 value,
367 CurveKey::<C>::random_n_with_each(&mut rng, my_alphas),
368 )
369 })
370 .unzip();
371 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
372 izip_eq!(all_unauth_shares, all_macs, all_keys)
373 .map(|(value, macs, keys)| PointShare::new(value, macs, keys))
374 .collect()
375 }
376}
377
378impl<C: Curve> RandomWith<(Point<C>, Vec<Vec<GlobalCurveKey<C>>>)> for PointShare<C> {
379 fn random_with(
380 _source: impl CryptoRngCore,
381 _data: (Point<C>, Vec<Vec<GlobalCurveKey<C>>>),
382 ) -> Self {
383 unimplemented!(
384 "Cannot discern what alpha to use for this peer. Use `random_n_with` instead."
385 );
386 }
387
388 fn random_n_with<Container: FromIterator<Self>>(
391 mut rng: impl CryptoRngCore,
392 n_parties: usize,
393 secret_value_and_alphas: (Point<C>, Vec<Vec<GlobalCurveKey<C>>>),
394 ) -> Container {
395 let (secret_value, all_alphas) = secret_value_and_alphas;
396 assert_eq!(
397 all_alphas.len(),
398 n_parties,
399 "Number of alphas must match the number of parties"
400 );
401 let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
402 let all_keys = all_alphas
403 .into_iter()
404 .map(|my_alphas| CurveKey::<C>::random_n_with_each(&mut rng, my_alphas))
405 .collect::<Vec<_>>();
406 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
407 izip_eq!(all_unauth_shares, all_macs, all_keys)
408 .map(|(value, macs, keys)| PointShare::new(value, macs, keys))
409 .collect()
410 }
411}
412
413impl<C: Curve> Add for PointShare<C> {
420 type Output = PointShare<C>;
421
422 #[inline]
423 fn add(self, other: PointShare<C>) -> Self::Output {
424 PointShare {
425 value: self.value + other.value,
426 keys: izip_eq!(self.keys, other.keys)
427 .map(|(a, b)| a + b)
428 .collect(),
429 macs: izip_eq!(self.macs, other.macs)
430 .map(|(a, b)| a + b)
431 .collect(),
432 }
433 }
434}
435
436impl<'a, C: Curve> Add for &'a PointShare<C> {
437 type Output = PointShare<C>;
438
439 #[inline]
440 fn add(self, other: &'a PointShare<C>) -> Self::Output {
441 PointShare {
442 value: self.value + other.value,
443 macs: izip_eq!(&self.macs, &other.macs)
444 .map(|(a, b)| a + b)
445 .collect(),
446 keys: izip_eq!(&self.keys, &other.keys)
447 .map(|(a, b)| a + b)
448 .collect(),
449 }
450 }
451}
452
453impl<C: Curve> Add<PointShare<C>> for &PointShare<C> {
454 type Output = PointShare<C>;
455
456 #[inline]
457 fn add(self, other: PointShare<C>) -> Self::Output {
458 PointShare {
459 value: self.value + other.value,
460 macs: izip_eq!(&self.macs, other.macs)
461 .map(|(a, b)| a + b)
462 .collect(),
463 keys: izip_eq!(&self.keys, other.keys)
464 .map(|(a, b)| a + b)
465 .collect(),
466 }
467 }
468}
469
470impl<'a, C: Curve> Add<&'a PointShare<C>> for PointShare<C> {
471 type Output = PointShare<C>;
472
473 #[inline]
474 fn add(self, other: &'a PointShare<C>) -> Self::Output {
475 PointShare {
476 value: self.value + other.value,
477 macs: izip_eq!(self.macs, &other.macs)
478 .map(|(a, b)| a + b)
479 .collect(),
480 keys: izip_eq!(self.keys, &other.keys)
481 .map(|(a, b)| a + b)
482 .collect(),
483 }
484 }
485}
486
487impl<C: Curve> AddAssign for PointShare<C> {
490 #[inline]
491 fn add_assign(&mut self, other: Self) {
492 self.value += other.value;
493 izip_eq!(&mut self.keys, other.keys).for_each(|(a, b)| *a += b);
494 izip_eq!(&mut self.macs, other.macs).for_each(|(a, b)| *a += b);
495 }
496}
497
498impl<'a, C: Curve> AddAssign<&'a PointShare<C>> for PointShare<C> {
499 #[inline]
500 fn add_assign(&mut self, other: &'a PointShare<C>) {
501 self.value += other.value;
502 izip_eq!(&mut self.keys, &other.keys).for_each(|(a, b)| *a += b);
503 izip_eq!(&mut self.macs, &other.macs).for_each(|(a, b)| *a += b);
504 }
505}
506
507impl<C: Curve> Sub for PointShare<C> {
510 type Output = PointShare<C>;
511
512 #[inline]
513 fn sub(self, other: PointShare<C>) -> Self::Output {
514 PointShare {
515 value: self.value - other.value,
516 macs: izip_eq!(self.macs, other.macs)
517 .map(|(a, b)| a - b)
518 .collect(),
519 keys: izip_eq!(self.keys, other.keys)
520 .map(|(a, b)| a - b)
521 .collect(),
522 }
523 }
524}
525
526impl<'a, C: Curve> Sub<&'a PointShare<C>> for &'a PointShare<C> {
527 type Output = PointShare<C>;
528
529 #[inline]
530 fn sub(self, other: &'a PointShare<C>) -> Self::Output {
531 PointShare {
532 value: self.value - other.value,
533 macs: izip_eq!(&self.macs, &other.macs)
534 .map(|(a, b)| a - b)
535 .collect(),
536 keys: izip_eq!(&self.keys, &other.keys)
537 .map(|(a, b)| a - b)
538 .collect(),
539 }
540 }
541}
542
543impl<C: Curve> Sub<PointShare<C>> for &PointShare<C> {
544 type Output = PointShare<C>;
545
546 #[inline]
547 fn sub(self, other: PointShare<C>) -> Self::Output {
548 PointShare {
549 value: self.value - other.value,
550 macs: izip_eq!(&self.macs, other.macs)
551 .map(|(a, b)| a - b)
552 .collect(),
553 keys: izip_eq!(&self.keys, other.keys)
554 .map(|(a, b)| a - b)
555 .collect(),
556 }
557 }
558}
559
560impl<'a, C: Curve> Sub<&'a PointShare<C>> for PointShare<C> {
561 type Output = PointShare<C>;
562
563 #[inline]
564 fn sub(self, other: &'a PointShare<C>) -> Self::Output {
565 PointShare {
566 value: self.value - other.value,
567 macs: izip_eq!(self.macs, &other.macs)
568 .map(|(a, b)| a - b)
569 .collect(),
570 keys: izip_eq!(self.keys, &other.keys)
571 .map(|(a, b)| a - b)
572 .collect(),
573 }
574 }
575}
576impl<C: Curve> SubAssign for PointShare<C> {
579 #[inline]
580 fn sub_assign(&mut self, other: Self) {
581 self.value -= other.value;
582 izip_eq!(&mut self.keys, other.keys).for_each(|(a, b)| *a -= b);
583 izip_eq!(&mut self.macs, other.macs).for_each(|(a, b)| *a -= b);
584 }
585}
586
587impl<'a, C: Curve> SubAssign<&'a PointShare<C>> for PointShare<C> {
588 #[inline]
589 fn sub_assign(&mut self, other: &'a PointShare<C>) {
590 self.value -= other.value;
591 izip_eq!(&mut self.keys, &other.keys).for_each(|(a, b)| *a -= b);
592 izip_eq!(&mut self.macs, &other.macs).for_each(|(a, b)| *a -= b);
593 }
594}
595
596impl<C: Curve> Mul<ScalarAsExtension<C>> for PointShare<C> {
599 type Output = PointShare<C>;
600
601 #[inline]
602 fn mul(mut self, other: ScalarAsExtension<C>) -> Self::Output {
603 self.value *= other;
604 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
605 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
606 self
607 }
608}
609
610impl<'a, C: Curve> Mul<&'a ScalarAsExtension<C>> for PointShare<C> {
611 type Output = PointShare<C>;
612
613 #[inline]
614 fn mul(mut self, other: &'a ScalarAsExtension<C>) -> Self::Output {
615 self.value *= other;
616 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
617 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
618 self
619 }
620}
621
622impl<C: Curve> Mul<ScalarAsExtension<C>> for &PointShare<C> {
623 type Output = PointShare<C>;
624
625 #[inline]
626 fn mul(self, other: ScalarAsExtension<C>) -> Self::Output {
627 PointShare {
628 value: self.value * other,
629 keys: self.keys.iter().map(|key| key * other).collect(),
630 macs: self.macs.iter().map(|mac| mac * other).collect(),
631 }
632 }
633}
634
635impl<'a, C: Curve> Mul<&'a ScalarAsExtension<C>> for &'a PointShare<C> {
636 type Output = PointShare<C>;
637
638 #[inline]
639 fn mul(self, other: &'a ScalarAsExtension<C>) -> Self::Output {
640 PointShare {
641 value: self.value * other,
642 keys: self.keys.iter().map(|key| key * other).collect(),
643 macs: self.macs.iter().map(|mac| mac * other).collect(),
644 }
645 }
646}
647
648impl<C: Curve> Mul<Scalar<C>> for PointShare<C> {
649 type Output = PointShare<C>;
650
651 #[inline]
652 fn mul(mut self, other: Scalar<C>) -> Self::Output {
653 self.value *= other;
654 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
655 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
656 self
657 }
658}
659
660impl<'a, C: Curve> Mul<&'a Scalar<C>> for PointShare<C> {
661 type Output = PointShare<C>;
662
663 #[inline]
664 fn mul(mut self, other: &'a Scalar<C>) -> Self::Output {
665 self.value *= other;
666 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
667 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
668 self
669 }
670}
671
672impl<C: Curve> Mul<Scalar<C>> for &PointShare<C> {
673 type Output = PointShare<C>;
674
675 #[inline]
676 fn mul(self, other: Scalar<C>) -> Self::Output {
677 PointShare {
678 value: self.value * other,
679 keys: self.keys.iter().map(|key| key * other).collect(),
680 macs: self.macs.iter().map(|mac| mac * other).collect(),
681 }
682 }
683}
684
685impl<'a, C: Curve> Mul<&'a Scalar<C>> for &'a PointShare<C> {
686 type Output = PointShare<C>;
687
688 #[inline]
689 fn mul(self, other: &'a Scalar<C>) -> Self::Output {
690 PointShare {
691 value: self.value * other,
692 keys: self.keys.iter().map(|key| key * other).collect(),
693 macs: self.macs.iter().map(|mac| mac * other).collect(),
694 }
695 }
696}
697
698impl<'a, C: Curve> MulAssign<&'a ScalarAsExtension<C>> for PointShare<C> {
701 #[inline]
702 fn mul_assign(&mut self, other: &'a ScalarAsExtension<C>) {
703 self.value *= other;
704 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
705 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
706 }
707}
708
709impl<'a, C: Curve> MulAssign<&'a Scalar<C>> for PointShare<C> {
710 #[inline]
711 fn mul_assign(&mut self, other: &'a Scalar<C>) {
712 self.value *= other;
713 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
714 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
715 }
716}
717
718impl<C: Curve> Neg for PointShare<C> {
721 type Output = Self;
722
723 #[inline]
724 fn neg(self) -> Self::Output {
725 PointShare {
726 value: -self.value,
727 keys: self.keys.iter().map(|key| -key).collect(),
728 macs: self.macs.iter().map(|mac| -mac).collect(),
729 }
730 }
731}
732
733impl<C: Curve> Neg for &PointShare<C> {
734 type Output = PointShare<C>;
735
736 #[inline]
737 fn neg(self) -> Self::Output {
738 PointShare {
739 value: -self.value,
740 keys: self.keys.iter().map(|key| -key).collect(),
741 macs: self.macs.iter().map(|mac| -mac).collect(),
742 }
743 }
744}
745
746impl<C: Curve> AddPlaintext for PointShare<C> {
749 type AssociatedInformation = IsFirstPeer;
750
751 #[inline]
754 fn add_plaintext(&self, constant: &Point<C>, is_peer_zero: IsFirstPeer) -> Self {
755 let result = self.clone();
756 result.add_plaintext_owned(constant, is_peer_zero)
757 }
758
759 #[inline]
762 fn add_plaintext_owned(mut self, constant: &Point<C>, is_peer_zero: IsFirstPeer) -> Self {
763 if is_peer_zero {
764 self.value += constant;
765 } else {
766 let key0 = self.keys.get_mut(0).expect("Missing key 0");
767 key0.beta -= *key0.alpha * constant;
768 }
769 self
770 }
771}
772
773impl<C: Curve> ConditionallySelectable for PointShare<C> {
776 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
777 PointShare {
778 value: Point::conditional_select(&a.value, &b.value, choice),
779 keys: izip_eq!(&a.keys, &b.keys)
780 .map(|(a, b)| CurveKey::conditional_select(a, b, choice))
781 .collect(),
782 macs: izip_eq!(&a.macs, &b.macs)
783 .map(|(a, b)| Point::conditional_select(a, b, choice))
784 .collect(),
785 }
786 }
787}
788
789impl<C: Curve> ConstantTimeEq for PointShare<C> {
790 #[inline]
791 fn ct_eq(&self, other: &Self) -> Choice {
792 self.value.ct_eq(&other.value)
793 & izip_eq!(&self.keys, &other.keys).fold(1.into(), |acc, (self_key, other_key)| {
794 acc & self_key.ct_eq(other_key)
795 })
796 & self.macs.ct_eq(&other.macs)
797 }
798}
799
800#[cfg(test)]
801mod tests {
802 use itertools::enumerate;
803
804 use super::*;
805 use crate::{
806 algebra::elliptic_curve::Curve25519Ristretto as C,
807 random::{self},
808 sharing::Verifiable,
809 };
810
811 pub type Value = Point<C>;
816 pub type Constant = Scalar<C>;
817 pub type Share = PointShare<C>;
818 pub type GlobalKey = GlobalCurveKey<C>;
819 pub const N_PARTIES: usize = 3;
822
823 #[test]
824 fn test_open_to() {
825 let mut rng = random::test_rng();
826 let local_share = Share::random_with(&mut rng, N_PARTIES);
827
828 for i in 0..N_PARTIES - 1 {
829 let open_share = local_share.open_to(i).unwrap();
830 assert_eq!(open_share.get_value(), &local_share.value);
831 assert_eq!(open_share.get_mac(), &local_share.macs[i]);
832 }
833 }
834
835 #[test]
836 fn test_random() {
837 let mut rng = random::test_rng();
838
839 let share = Share::random_with(&mut rng, N_PARTIES);
841 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
842 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
843
844 let value = &Value::random(&mut rng);
846 let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
847 assert_eq!(share_with_value.get_value(), value);
848 assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
849 assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
850 }
851
852 #[test]
853 fn test_random_vec_and_reconstruct() {
854 let mut rng = random::test_rng();
855
856 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
858 assert_eq!(shares.len(), N_PARTIES);
859 for share in &shares {
860 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
861 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
862 }
863 let unauthenticated_shares = shares
864 .iter()
865 .map(|s| s.get_value().to_owned())
866 .collect::<Vec<_>>();
867 let expected = Value::from_additive_shares(&unauthenticated_shares);
868 let reconstructed = Share::reconstruct_all(&shares).unwrap();
869 assert_eq!(reconstructed, expected);
870
871 let value = &Value::random(&mut rng);
873 let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
874 assert_eq!(shares.len(), N_PARTIES);
875 for share in &shares {
876 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
877 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
878 }
879 let reconstructed = Share::reconstruct_all(&shares).unwrap();
880 assert_eq!(reconstructed, value.to_owned());
881 }
882
883 #[test]
884 fn test_random_vec_with_global_key_and_reconstruct() {
885 let mut rng = random::test_rng();
886
887 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
889 let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
890 assert_eq!(shares_from_alphas.len(), N_PARTIES);
891 for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
892 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
893 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
894 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
895 }
896 Share::verify_all(&shares_from_alphas).unwrap(); let value = &Value::random(&mut rng);
900 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
901 let shares_from_value_and_alphas: Vec<_> =
902 Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
903 assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
904 for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
905 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
906 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
907 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
908 }
909 let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
910 assert_eq!(&reconstructed, value);
911
912 let value = Value::random(&mut rng);
914 let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
915 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
916 let shares_from_unauth_and_alphas: Vec<_> =
917 Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
918 assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
919 for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
920 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
921 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
922 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
923 }
924 let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
925 assert_eq!(reconstructed, value);
926 }
927
928 #[test]
929 fn test_verify_mac() {
930 let mut rng = random::test_rng();
931
932 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
933
934 enumerate(shares.iter()).for_each(|(i, s_i)| {
936 enumerate(shares.iter())
937 .filter(|(j, _)| i != *j)
938 .for_each(|(j, s_j)| {
939 let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
940 s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
941 });
942 });
943
944 Share::verify_all(&shares).unwrap();
946 }
947
948 #[test]
949 fn test_add() {
950 let mut rng = random::test_rng();
951
952 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
953 let a = &Value::random(&mut rng);
954 let b = &Value::random(&mut rng);
955
956 let shares_a: Vec<_> =
957 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
958 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
959
960 let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
962 .map(|(share_a, share_b)| share_a + share_b)
963 .collect::<Vec<_>>();
964 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
965 assert_eq!(reconstructed, a + b);
966
967 let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
969 .map(|(share_a, share_b)| share_a + share_b)
970 .collect::<Vec<_>>();
971 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
972 assert_eq!(reconstructed, a + b);
973
974 let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
976 .map(|(share_a, share_b)| share_a + share_b)
977 .collect::<Vec<_>>();
978 let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
979 assert_eq!(reconstructed, a + b);
980
981 let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
983 .map(|(share_a, share_b)| share_a + share_b)
984 .collect::<Vec<_>>();
985 let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
986 assert_eq!(reconstructed, a + b);
987
988 let mut shares_a_add_assign_b_ref = shares_a.clone();
990 izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
991 .for_each(|(share_a, share_b)| *share_a += share_b);
992 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
993 assert_eq!(reconstructed, a + b);
994
995 let mut shares_a_add_assign_b = shares_a.clone();
997 izip_eq!(&mut shares_a_add_assign_b, shares_b)
998 .for_each(|(share_a, share_b)| *share_a += share_b);
999 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
1000 assert_eq!(reconstructed, a + b);
1001 }
1002
1003 #[test]
1004 fn test_add_secret() {
1005 let mut rng = random::test_rng();
1006
1007 let a = &Value::random(&mut rng);
1008 let k = &Value::random(&mut rng);
1009
1010 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1011
1012 let shares_a_plus_k_ref = enumerate(shares_a.iter())
1014 .map(|(i, share_a)| share_a.add_plaintext(k, i == 0))
1015 .collect::<Vec<_>>();
1016 let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
1017 assert_eq!(reconstructed, a + k);
1018
1019 let shares_a_plus_k = enumerate(shares_a)
1021 .map(|(i, share_a)| share_a.add_plaintext_owned(k, i == 0))
1022 .collect::<Vec<_>>();
1023 let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
1024 assert_eq!(reconstructed, a + k);
1025 }
1026
1027 #[test]
1028 fn test_mul_constant() {
1029 let mut rng = random::test_rng();
1030
1031 let a = &Value::random(&mut rng);
1032 let k = &Constant::random(&mut rng);
1033
1034 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1035
1036 let shares_a_times_k = izip_eq!(shares_a.clone())
1038 .map(|share_a| share_a * k)
1039 .collect::<Vec<_>>();
1040 let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
1041 assert_eq!(reconstructed, a * k);
1042
1043 let mut shares_a_times_k_assign = shares_a.clone();
1045 izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
1046 let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
1047 assert_eq!(reconstructed, a * k);
1048 }
1049
1050 #[test]
1051 fn test_sub() {
1052 let mut rng = random::test_rng();
1053 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1054
1055 let a = &Value::random(&mut rng);
1056 let b = &Value::random(&mut rng);
1057
1058 let shares_a: Vec<_> =
1059 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1060 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1061
1062 let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
1064 .map(|(share_a, share_b)| share_a - share_b)
1065 .collect::<Vec<_>>();
1066
1067 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
1068 assert_eq!(reconstructed, a - b);
1069
1070 let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
1072 .map(|(share_a, share_b)| share_a - share_b)
1073 .collect::<Vec<_>>();
1074 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
1075 assert_eq!(reconstructed, a - b);
1076
1077 let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1079 .map(|(share_a, share_b)| share_a - share_b)
1080 .collect::<Vec<_>>();
1081 let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
1082 assert_eq!(reconstructed, a - b);
1083
1084 let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1086 .map(|(share_a, share_b)| share_a - share_b)
1087 .collect::<Vec<_>>();
1088 let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
1089 assert_eq!(reconstructed, a - b);
1090
1091 let mut shares_a_sub_assign_b_ref = shares_a.clone();
1093 izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
1094 .for_each(|(share_a, share_b)| *share_a -= share_b);
1095 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
1096 assert_eq!(reconstructed, a - b);
1097
1098 let mut shares_a_sub_assign_b = shares_a.clone();
1100 izip_eq!(&mut shares_a_sub_assign_b, shares_b)
1101 .for_each(|(share_a, share_b)| *share_a -= share_b);
1102 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
1103 assert_eq!(reconstructed, a - b);
1104 }
1105
1106 #[test]
1107 fn test_neg() {
1108 let mut rng = random::test_rng();
1109
1110 let a = Value::random(&mut rng);
1111
1112 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1113
1114 let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
1116 let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
1117 assert_eq!(reconstructed, -a.to_owned());
1118
1119 let shares_a_neg = shares_a
1121 .into_iter()
1122 .map(|share_a| -share_a)
1123 .collect::<Vec<_>>();
1124 let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
1125 assert_eq!(reconstructed, -a.to_owned());
1126 }
1127
1128 #[test]
1129 fn test_conditional_select() {
1130 let mut rng = random::test_rng();
1131
1132 let shares_a = Share::random_with(&mut rng, N_PARTIES);
1133 let shares_b = Share::random_with(&mut rng, N_PARTIES);
1134
1135 let choice = Choice::from(0u8);
1137 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1138 assert_eq!(selected, shares_a);
1139
1140 let choice = Choice::from(1u8);
1142 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1143 assert_eq!(selected, shares_b);
1144 }
1145
1146 #[test]
1147 fn test_ct_eq() {
1148 let mut rng = random::test_rng();
1149
1150 let shares_a = Share::random_with(&mut rng, N_PARTIES);
1151 let shares_b = Share::random_with(&mut rng, N_PARTIES);
1152
1153 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
1155 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
1156 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
1157 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
1158 }
1159}