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