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