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::PrimitiveError,
14 izip_eq,
15 random::{CryptoRngCore, Random, RandomWith},
16 sharing::{
17 authenticated::NParties,
18 unauthenticated::AdditiveShares,
19 GlobalCurveKey,
20 Reconstructible,
21 VerifiableWith,
22 },
23 types::{
24 heap_array::curve_arrays::{CurvePoints, Scalars, ScalarsAsExtension},
25 CollectAll,
26 ConditionallySelectable,
27 PeerIndex,
28 Positive,
29 },
30 utils::IntoExactSizeIterator,
31};
32#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(bound = "C: Curve, M: Positive")]
34pub struct OpenPointShares<C: Curve, M: Positive> {
35 pub(crate) value: CurvePoints<C, M>,
36 pub(crate) mac: CurvePoints<C, M>,
37}
38
39impl<C: Curve, M: Positive> OpenPointShares<C, M> {
40 pub fn new(value: CurvePoints<C, M>, mac: CurvePoints<C, M>) -> Self {
41 Self { value, mac }
42 }
43
44 pub fn get_value(&self) -> &CurvePoints<C, M> {
45 &self.value
46 }
47
48 pub fn get_mac(&self) -> &CurvePoints<C, M> {
49 &self.mac
50 }
51}
52
53impl<C: Curve, M: Positive> Debug for OpenPointShares<C, M> {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 f.debug_struct(format!("OpenPointShares<{}>", M::USIZE).as_str())
56 .field("value", &self.value)
57 .field("mac", &self.mac)
58 .finish()
59 }
60}
61
62#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
65#[serde(bound = "C: Curve")]
66pub struct PointShares<C: Curve, M: Positive> {
67 pub(crate) value: CurvePoints<C, M>, pub(crate) macs: Box<[CurvePoints<C, M>]>, pub(crate) keys: Box<[CurveKeys<C, M>]>, }
71
72impl<C: Curve, M: Positive> PointShares<C, M> {
73 pub fn try_new(
74 value: CurvePoints<C, M>,
75 macs: Box<[CurvePoints<C, M>]>,
76 keys: Box<[CurveKeys<C, M>]>,
77 ) -> Result<Self, PrimitiveError> {
78 if macs.is_empty() {
79 return Err(PrimitiveError::MinimumLength(2, 0));
80 }
81 if macs.len() != keys.len() {
82 return Err(PrimitiveError::InvalidSize(keys.len(), macs.len()));
83 }
84 Ok(Self { value, macs, keys })
86 }
87
88 fn new(
89 value: CurvePoints<C, M>,
90 macs: Box<[CurvePoints<C, M>]>,
91 keys: Box<[CurveKeys<C, M>]>,
92 ) -> Self {
93 Self { value, macs, keys }
94 }
95
96 pub fn get_value(&self) -> &CurvePoints<C, M> {
97 &self.value
98 }
99
100 pub fn get_keys(&self) -> &[CurveKeys<C, M>] {
101 &self.keys
102 }
103
104 pub fn get_key(&self, index: PeerIndex) -> Option<&CurveKeys<C, M>> {
105 self.keys.get(index)
106 }
107
108 pub fn get_macs(&self) -> &[CurvePoints<C, M>] {
109 &self.macs
110 }
111
112 pub fn get_mac(&self, index: PeerIndex) -> Option<&CurvePoints<C, M>> {
113 self.macs.get(index)
114 }
115
116 #[inline]
117 pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalCurveKey<C>> + '_ {
118 self.keys.iter().map(|key| key.get_alpha())
119 }
120}
121
122impl<C: Curve, M: Positive> VerifiableWith for PointShares<C, M> {
126 type VerificationData = ();
127 #[inline]
129 fn verify_from_peer_with(
130 &self,
131 open_share: &OpenPointShares<C, M>,
132 peer: PeerIndex,
133 _verification_data: (),
134 ) -> Result<(), PrimitiveError> {
135 self.get_key(peer)
136 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?
137 .verify_mac(open_share)
138 .map_err(|e| e.blame(peer))
139 }
140
141 #[inline]
143 fn verify_with(
144 &self,
145 open_shares: &[OpenPointShares<C, M>],
146 _verification_data: (),
147 ) -> Result<(), PrimitiveError> {
148 enumerate(izip_eq!(open_shares, &self.keys))
149 .map(|(from_peer, (open_share, key))| {
150 key.verify_mac(open_share).map_err(|e| e.blame(from_peer))
151 })
152 .collect_errors()?;
153 Ok(())
154 }
155}
156
157impl<C: Curve, M: Positive> Reconstructible for PointShares<C, M> {
162 type Opening = OpenPointShares<C, M>;
163 type Secret = CurvePoints<C, M>;
164
165 fn open_to(&self, peer: PeerIndex) -> Result<OpenPointShares<C, M>, PrimitiveError> {
167 let mac = self
168 .get_mac(peer)
169 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.macs.len()))?
170 .to_owned();
171 Ok(OpenPointShares::new(self.get_value().to_owned(), mac))
172 }
173
174 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenPointShares<C, M>> {
176 self.get_macs()
177 .iter()
178 .map(|mac| OpenPointShares::new(self.get_value().to_owned(), mac.to_owned()))
179 }
180
181 fn reconstruct(
183 &self,
184 openings: &[OpenPointShares<C, M>],
185 ) -> Result<Self::Secret, PrimitiveError> {
186 if openings.len() != self.get_keys().len() {
187 return Err(PrimitiveError::InvalidSize(
188 self.get_keys().len(),
189 openings.len(),
190 ));
191 }
192 self.verify_with(openings, ())?;
193 Ok(openings
194 .iter()
195 .fold(self.get_value().to_owned(), |acc, open_share| {
196 acc + open_share.get_value()
197 }))
198 }
199}
200
201fn compute_macs<C: Curve, M: Positive>(
206 all_unauth_shares: &[CurvePoints<C, M>],
207 all_keys: &[Box<[CurveKeys<C, M>]>],
208) -> Vec<Box<[CurvePoints<C, M>]>> {
209 let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
210 enumerate(all_unauth_shares.iter())
211 .map(|(i, my_unauth_share)| {
212 enumerate(all_key_iters.iter_mut())
213 .filter(|(j, _)| *j != i)
214 .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
215 .collect()
216 })
217 .collect()
218}
219
220impl<C: Curve, M: Positive> Random for PointShares<C, M> {
221 fn random(_rng: impl CryptoRngCore) -> Self {
222 unimplemented!(
223 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
224 std::any::type_name::<Self>()
225 )
226 }
227
228 fn random_n<Container: FromIterator<Self>>(
230 mut rng: impl CryptoRngCore,
231 n_parties: NParties,
232 ) -> Container {
233 let all_unauth_shares: Vec<_> = CurvePoints::random_n(&mut rng, n_parties);
234 let all_keys = (0..n_parties)
235 .map(|_| CurveKeys::<C, M>::random_n(&mut rng, n_parties - 1))
236 .collect::<Vec<_>>();
237 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
238 izip_eq!(all_unauth_shares, all_macs, all_keys)
239 .map(|(value, macs, keys)| PointShares::new(value, macs, keys))
240 .collect()
241 }
242}
243
244impl<C: Curve, M: Positive> RandomWith<NParties> for PointShares<C, M> {
245 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
247 PointShares::new(
248 CurvePoints::<C, M>::random(&mut rng),
249 CurvePoints::<C, M>::random_n(&mut rng, n_parties - 1),
250 CurveKeys::<C, M>::random_n(&mut rng, n_parties - 1),
251 )
252 }
253}
254
255impl<C: Curve, M: Positive> RandomWith<(NParties, CurvePoints<C, M>)> for PointShares<C, M> {
256 fn random_with(
258 mut rng: impl CryptoRngCore,
259 n_parties_value: (NParties, CurvePoints<C, M>),
260 ) -> Self {
261 let (n_parties, value) = n_parties_value;
262 PointShares::new(
263 value,
264 CurvePoints::<C, M>::random_n(&mut rng, n_parties - 1),
265 CurveKeys::<C, M>::random_n(&mut rng, n_parties - 1),
266 )
267 }
268}
269
270impl<C: Curve, M: Positive> RandomWith<CurvePoints<C, M>> for PointShares<C, M> {
271 fn random_with(_rng: impl CryptoRngCore, _data: CurvePoints<C, M>) -> 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: usize,
283 value: CurvePoints<C, M>,
284 ) -> Container {
285 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
286 let all_keys = (0..n_parties)
287 .map(|_| CurveKeys::<C, M>::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)| PointShares::new(value, macs, keys))
292 .collect()
293 }
294
295 fn random_n_with_each<Container: FromIterator<Self>>(
298 mut rng: impl CryptoRngCore,
299 n_parties_and_value: impl IntoExactSizeIterator<Item = CurvePoints<C, M>>,
300 ) -> Container {
301 let all_unauth_shares = n_parties_and_value.into_iter().collect::<Vec<_>>();
302 let n_parties = all_unauth_shares.len();
303 let all_keys = (0..n_parties)
304 .map(|_| CurveKeys::<C, M>::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)| PointShares::new(value, macs, keys))
309 .collect()
310 }
311}
312
313impl<C: Curve, M: Positive> RandomWith<Vec<GlobalCurveKey<C>>> for PointShares<C, M> {
314 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalCurveKey<C>>) -> Self {
316 let n_other_parties = alphas.len();
317 PointShares::new(
318 CurvePoints::random(&mut rng),
319 CurvePoints::<C, M>::random_n(&mut rng, n_other_parties),
320 CurveKeys::<C, M>::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<_> = CurvePoints::random_n(&mut rng, all_alphas.len());
331 let all_keys = all_alphas
332 .into_iter()
333 .map(|my_alphas| CurveKeys::<C, M>::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)| PointShares::new(value, macs, keys))
338 .collect()
339 }
340}
341
342impl<C: Curve, M: Positive> RandomWith<(CurvePoints<C, M>, Vec<GlobalCurveKey<C>>)>
343 for PointShares<C, M>
344{
345 fn random_with(
347 mut rng: impl CryptoRngCore,
348 value_alphas: (CurvePoints<C, M>, Vec<GlobalCurveKey<C>>),
349 ) -> Self {
350 let (value, alphas) = value_alphas;
351 let n_other_parties = alphas.len();
352 PointShares::new(
353 value,
354 CurvePoints::<C, M>::random_n(&mut rng, n_other_parties),
355 CurveKeys::<C, M>::random_n_with_each(&mut rng, alphas),
356 )
357 }
358
359 fn random_n_with_each<Container: FromIterator<Self>>(
361 mut rng: impl CryptoRngCore,
362 unauth_shares_and_alphas: impl IntoIterator<Item = (CurvePoints<C, M>, Vec<GlobalCurveKey<C>>)>,
363 ) -> Container {
364 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
365 .into_iter()
366 .map(|(value, my_alphas)| {
367 (
368 value,
369 CurveKeys::<C, M>::random_n_with_each(&mut rng, my_alphas),
370 )
371 })
372 .unzip();
373 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
374 izip_eq!(all_unauth_shares, all_macs, all_keys)
375 .map(|(value, macs, keys)| PointShares::new(value, macs, keys))
376 .collect()
377 }
378}
379
380impl<C: Curve, M: Positive> RandomWith<(CurvePoints<C, M>, Vec<Vec<GlobalCurveKey<C>>>)>
381 for PointShares<C, M>
382{
383 fn random_with(
384 _rng: impl CryptoRngCore,
385 _data: (CurvePoints<C, M>, Vec<Vec<GlobalCurveKey<C>>>),
386 ) -> Self {
387 unimplemented!(
388 "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
389 );
390 }
391
392 fn random_n_with<Container: FromIterator<Self>>(
395 mut rng: impl CryptoRngCore,
396 n_parties: usize,
397 secret_value_and_alphas: (CurvePoints<C, M>, Vec<Vec<GlobalCurveKey<C>>>),
398 ) -> Container {
399 let (secret_value, all_alphas) = secret_value_and_alphas;
400 assert_eq!(all_alphas.len(), n_parties);
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| CurveKeys::<C, M>::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)| PointShares::new(value, macs, keys))
409 .collect()
410 }
411}
412
413#[macros::op_variants(owned, borrowed, flipped_commutative)]
420impl<'a, C: Curve, M: Positive> Add<&'a PointShares<C, M>> for PointShares<C, M> {
421 type Output = PointShares<C, M>;
422
423 #[inline]
424 fn add(mut self, other: &'a PointShares<C, M>) -> Self::Output {
425 self.value += &other.value;
426 izip_eq!(&mut self.macs, &other.macs).for_each(|(a, b)| *a += b);
427 izip_eq!(&mut self.keys, &other.keys).for_each(|(a, b)| *a += b);
428 self
429 }
430}
431
432#[macros::op_variants(owned)]
433impl<'a, C: Curve, M: Positive> AddAssign<&'a PointShares<C, M>> for PointShares<C, M> {
434 #[inline]
435 fn add_assign(&mut self, other: &'a PointShares<C, M>) {
436 self.value += &other.value;
437 izip_eq!(&mut self.macs, &other.macs).for_each(|(a, b)| *a += b);
438 izip_eq!(&mut self.keys, &other.keys).for_each(|(a, b)| *a += b);
439 }
440}
441
442#[macros::op_variants(owned, borrowed, flipped)]
445impl<'a, C: Curve, M: Positive> Sub<&'a PointShares<C, M>> for PointShares<C, M> {
446 type Output = PointShares<C, M>;
447
448 #[inline]
449 fn sub(mut self, other: &'a PointShares<C, M>) -> Self::Output {
450 self.value -= &other.value;
451 izip_eq!(&mut self.macs, &other.macs).for_each(|(a, b)| *a -= b);
452 izip_eq!(&mut self.keys, &other.keys).for_each(|(a, b)| *a -= b);
453 self
454 }
455}
456
457#[macros::op_variants(owned)]
458impl<'a, C: Curve, M: Positive> SubAssign<&'a PointShares<C, M>> for PointShares<C, M> {
459 #[inline]
460 fn sub_assign(&mut self, other: &'a PointShares<C, M>) {
461 self.value -= &other.value;
462 izip_eq!(&mut self.macs, &other.macs).for_each(|(a, b)| *a -= b);
463 izip_eq!(&mut self.keys, &other.keys).for_each(|(a, b)| *a -= b);
464 }
465}
466
467#[macros::op_variants(owned, borrowed)]
470impl<'a, C: Curve, M: Positive> Mul<&'a ScalarAsExtension<C>> for PointShares<C, M> {
471 type Output = PointShares<C, M>;
472
473 #[inline]
474 fn mul(mut self, other: &'a ScalarAsExtension<C>) -> Self::Output {
475 self.value *= other;
476 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
477 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
478 self
479 }
480}
481
482#[macros::op_variants(owned, borrowed)]
483impl<'a, C: Curve, M: Positive> Mul<&'a Scalar<C>> for PointShares<C, M> {
484 type Output = PointShares<C, M>;
485
486 #[inline]
487 fn mul(mut self, other: &'a Scalar<C>) -> Self::Output {
488 self.value *= other;
489 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
490 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
491 self
492 }
493}
494
495#[macros::op_variants(owned, borrowed)]
496impl<'a, C: Curve, M: Positive> Mul<&'a ScalarsAsExtension<C, M>> for PointShares<C, M> {
497 type Output = PointShares<C, M>;
498
499 #[inline]
500 fn mul(mut self, other: &'a ScalarsAsExtension<C, M>) -> Self::Output {
501 self.value *= other;
502 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
503 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
504 self
505 }
506}
507
508#[macros::op_variants(owned, borrowed)]
509impl<'a, C: Curve, M: Positive> Mul<&'a Scalars<C, M>> for PointShares<C, M> {
510 type Output = PointShares<C, M>;
511
512 #[inline]
513 fn mul(mut self, other: &'a Scalars<C, M>) -> Self::Output {
514 self.value *= other;
515 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
516 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
517 self
518 }
519}
520
521#[macros::op_variants(owned)]
524impl<'a, C: Curve, M: Positive> MulAssign<&'a ScalarAsExtension<C>> for PointShares<C, M> {
525 #[inline]
526 fn mul_assign(&mut self, other: &'a ScalarAsExtension<C>) {
527 self.value *= other;
528 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
529 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
530 }
531}
532
533#[macros::op_variants(owned)]
534impl<'a, C: Curve, M: Positive> MulAssign<&'a Scalar<C>> for PointShares<C, M> {
535 #[inline]
536 fn mul_assign(&mut self, other: &'a Scalar<C>) {
537 self.value *= other;
538 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
539 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
540 }
541}
542
543#[macros::op_variants(owned)]
544impl<'a, C: Curve, M: Positive> MulAssign<&'a ScalarsAsExtension<C, M>> for PointShares<C, M> {
545 #[inline]
546 fn mul_assign(&mut self, other: &'a ScalarsAsExtension<C, M>) {
547 self.value *= other;
548 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
549 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
550 }
551}
552
553#[macros::op_variants(owned)]
554impl<'a, C: Curve, M: Positive> MulAssign<&'a Scalars<C, M>> for PointShares<C, M> {
555 #[inline]
556 fn mul_assign(&mut self, other: &'a Scalars<C, M>) {
557 self.value *= other;
558 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
559 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
560 }
561}
562
563#[macros::op_variants(borrowed)]
566impl<C: Curve, M: Positive> Neg for PointShares<C, M> {
567 type Output = PointShares<C, M>;
568
569 #[inline]
570 fn neg(self) -> Self::Output {
571 PointShares {
572 value: -self.value,
573 keys: izip_eq!(self.keys).map(|key| -key).collect(),
574 macs: izip_eq!(self.macs).map(|mac| -mac).collect(),
575 }
576 }
577}
578
579impl<C: Curve, M: Positive> PointShares<C, M> {
582 #[inline]
585 pub fn add_secret_owned(mut self, constant: &CurvePoints<C, M>, is_peer_zero: bool) -> Self {
586 if is_peer_zero {
587 self.value += constant;
588 } else {
589 let key0 = self.keys.get_mut(0).expect("Missing key 0");
590 key0.betas -= constant * *key0.alpha;
591 }
592 self
593 }
594
595 #[inline]
598 pub fn add_secret(&self, constant: &CurvePoints<C, M>, is_peer_zero: bool) -> Self {
599 let result = self.clone();
600 result.add_secret_owned(constant, is_peer_zero)
601 }
602}
603
604impl<C: Curve, M: Positive> ConstantTimeEq for PointShares<C, M> {
607 #[inline]
608 fn ct_eq(&self, other: &Self) -> Choice {
609 self.value.ct_eq(&other.value) & self.keys.ct_eq(&other.keys) & self.macs.ct_eq(&other.macs)
610 }
611}
612
613impl<C: Curve, M: Positive> ConditionallySelectable for PointShares<C, M> {
614 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
615 PointShares {
616 value: CurvePoints::conditional_select(&a.value, &b.value, choice),
617 macs: izip_eq!(&a.macs, &b.macs)
618 .map(|(a, b)| CurvePoints::conditional_select(a, b, choice))
619 .collect(),
620 keys: izip_eq!(&a.keys, &b.keys)
621 .map(|(a, b)| CurveKeys::conditional_select(a, b, choice))
622 .collect(),
623 }
624 }
625}
626
627#[cfg(test)]
628mod tests {
629
630 use itertools::enumerate;
631 use typenum::U12;
632
633 use super::*;
634 use crate::{
635 algebra::elliptic_curve::Curve25519Ristretto as C,
636 random,
637 sharing::Verifiable,
638 types::heap_array::curve_arrays::Scalars,
639 };
640
641 pub type M = U12;
646 pub type Value = CurvePoints<C, M>;
647 pub type Constant = Scalars<C, M>;
648 pub type Share = PointShares<C, M>;
649 pub type GlobalKey = GlobalCurveKey<C>;
650 pub const N_PARTIES: usize = 3;
653
654 #[test]
655 fn test_open_to() {
656 let mut rng = random::test_rng();
657 let local_share = Share::random_with(&mut rng, N_PARTIES);
658
659 for i in 0..N_PARTIES - 1 {
660 let open_share = local_share.open_to(i).unwrap();
661 assert_eq!(open_share.get_value(), &local_share.value);
662 assert_eq!(open_share.get_mac(), &local_share.macs[i]);
663 }
664 }
665
666 #[test]
667 fn test_random() {
668 let mut rng = random::test_rng();
669
670 let share = Share::random_with(&mut rng, N_PARTIES);
672 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
673 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
674
675 let value = &Value::random(&mut rng);
677 let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
678 assert_eq!(share_with_value.get_value(), value);
679 assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
680 assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
681 }
682
683 #[test]
684 fn test_random_vec_and_reconstruct() {
685 let mut rng = random::test_rng();
686
687 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
689 assert_eq!(shares.len(), N_PARTIES);
690 for share in &shares {
691 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
692 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
693 }
694 let unauthenticated_shares = shares
695 .iter()
696 .map(|s| s.get_value().to_owned())
697 .collect::<Vec<_>>();
698 let expected = Value::from_additive_shares(&unauthenticated_shares);
699 let reconstructed = Share::reconstruct_all(&shares).unwrap();
700 assert_eq!(reconstructed, expected);
701
702 let value = &Value::random(&mut rng);
704 let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
705 assert_eq!(shares.len(), N_PARTIES);
706 for share in &shares {
707 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
708 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
709 }
710 let reconstructed = Share::reconstruct_all(&shares).unwrap();
711 assert_eq!(reconstructed, value.to_owned());
712 }
713
714 #[test]
715 fn test_random_vec_with_global_key_and_reconstruct() {
716 let mut rng = random::test_rng();
717
718 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
720 let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
721 assert_eq!(shares_from_alphas.len(), N_PARTIES);
722 for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
723 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
724 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
725 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
726 }
727 let _ = Share::reconstruct_all(&shares_from_alphas).unwrap(); let value = &Value::random(&mut rng);
731 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
732 let shares_from_value_and_alphas: Vec<_> =
733 Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
734 assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
735 for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
736 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
737 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
738 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
739 }
740 let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
741 assert_eq!(&reconstructed, value);
742
743 let value = Value::random(&mut rng);
745 let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
746 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
747 let shares_from_unauth_and_alphas: Vec<_> =
748 Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
749 assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
750 for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
751 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
752 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
753 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
754 }
755 let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
756 assert_eq!(reconstructed, value);
757 }
758
759 #[test]
760 fn test_verify_mac() {
761 let mut rng = random::test_rng();
762
763 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
764
765 enumerate(shares.iter()).for_each(|(i, s_i)| {
767 enumerate(shares.iter())
768 .filter(|(j, _)| i != *j)
769 .for_each(|(j, s_j)| {
770 let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
771 s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
772 });
773 });
774
775 Share::verify_all(&shares).unwrap();
777 }
778
779 #[test]
780 fn test_add() {
781 let mut rng = random::test_rng();
782
783 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
784 let a = &Value::random(&mut rng);
785 let b = &Value::random(&mut rng);
786
787 let shares_a: Vec<_> =
788 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
789 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
790
791 let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
793 .map(|(share_a, share_b)| share_a + share_b)
794 .collect::<Vec<_>>();
795 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
796 assert_eq!(reconstructed, a + b);
797
798 let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
800 .map(|(share_a, share_b)| share_a + share_b)
801 .collect::<Vec<_>>();
802 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
803 assert_eq!(reconstructed, a + b);
804
805 let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
807 .map(|(share_a, share_b)| share_a + share_b)
808 .collect::<Vec<_>>();
809 let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
810 assert_eq!(reconstructed, a + b);
811
812 let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
814 .map(|(share_a, share_b)| share_a + share_b)
815 .collect::<Vec<_>>();
816 let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
817 assert_eq!(reconstructed, a + b);
818
819 let mut shares_a_add_assign_b_ref = shares_a.clone();
821 izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
822 .for_each(|(share_a, share_b)| *share_a += share_b);
823 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
824 assert_eq!(reconstructed, a + b);
825
826 let mut shares_a_add_assign_b = shares_a.clone();
828 izip_eq!(&mut shares_a_add_assign_b, shares_b)
829 .for_each(|(share_a, share_b)| *share_a += share_b);
830 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
831 assert_eq!(reconstructed, a + b);
832 }
833
834 #[test]
835 fn test_add_secret() {
836 let mut rng = random::test_rng();
837
838 let a = &Value::random(&mut rng);
839 let k = &Value::random(&mut rng);
840
841 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
842
843 let shares_a_plus_k_ref = enumerate(shares_a.iter())
845 .map(|(i, share_a)| share_a.add_secret(k, i == 0))
846 .collect::<Vec<_>>();
847 let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
848 assert_eq!(reconstructed, a + k);
849
850 let shares_a_plus_k = enumerate(shares_a)
852 .map(|(i, share_a)| share_a.add_secret_owned(k, i == 0))
853 .collect::<Vec<_>>();
854 let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
855 assert_eq!(reconstructed, a + k);
856 }
857
858 #[test]
859 fn test_mul_constant() {
860 let mut rng = random::test_rng();
861
862 let a = &Value::random(&mut rng);
863 let k = &Constant::random(&mut rng);
864
865 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
866
867 let shares_a_times_k = izip_eq!(shares_a.clone())
869 .map(|share_a| share_a * k)
870 .collect::<Vec<_>>();
871 let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
872 assert_eq!(reconstructed, a * k);
873
874 let mut shares_a_times_k_assign = shares_a.clone();
876 izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
877 let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
878 assert_eq!(reconstructed, a * k);
879 }
880
881 #[test]
882 fn test_sub() {
883 let mut rng = random::test_rng();
884 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
885
886 let a = &Value::random(&mut rng);
887 let b = &Value::random(&mut rng);
888
889 let shares_a: Vec<_> =
890 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
891 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
892
893 let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
895 .map(|(share_a, share_b)| share_a - share_b)
896 .collect::<Vec<_>>();
897
898 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
899 assert_eq!(reconstructed, a - b);
900
901 let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
903 .map(|(share_a, share_b)| share_a - share_b)
904 .collect::<Vec<_>>();
905 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
906 assert_eq!(reconstructed, a - b);
907
908 let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
910 .map(|(share_a, share_b)| share_a - share_b)
911 .collect::<Vec<_>>();
912 let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
913 assert_eq!(reconstructed, a - b);
914
915 let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
917 .map(|(share_a, share_b)| share_a - share_b)
918 .collect::<Vec<_>>();
919 let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
920 assert_eq!(reconstructed, a - b);
921
922 let mut shares_a_sub_assign_b_ref = shares_a.clone();
924 izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
925 .for_each(|(share_a, share_b)| *share_a -= share_b);
926 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
927 assert_eq!(reconstructed, a - b);
928
929 let mut shares_a_sub_assign_b = shares_a.clone();
931 izip_eq!(&mut shares_a_sub_assign_b, shares_b)
932 .for_each(|(share_a, share_b)| *share_a -= share_b);
933 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
934 assert_eq!(reconstructed, a - b);
935 }
936
937 #[test]
938 fn test_neg() {
939 let mut rng = random::test_rng();
940
941 let a = Value::random(&mut rng);
942
943 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
944
945 let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
947 let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
948 assert_eq!(reconstructed, -a.to_owned());
949
950 let shares_a_neg = shares_a
952 .into_iter()
953 .map(|share_a| -share_a)
954 .collect::<Vec<_>>();
955 let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
956 assert_eq!(reconstructed, -a.to_owned());
957 }
958
959 #[test]
960 fn test_conditional_select() {
961 let mut rng = random::test_rng();
962
963 let shares_a = Share::random_with(&mut rng, N_PARTIES);
964 let shares_b = Share::random_with(&mut rng, N_PARTIES);
965
966 let choice = Choice::from(0u8);
968 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
969 assert_eq!(selected, shares_a);
970
971 let choice = Choice::from(1u8);
973 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
974 assert_eq!(selected, shares_b);
975 }
976
977 #[test]
978 fn test_ct_eq() {
979 let mut rng = random::test_rng();
980
981 let shares_a = Share::random_with(&mut rng, N_PARTIES);
982 let shares_b = Share::random_with(&mut rng, N_PARTIES);
983
984 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
986 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
987 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
988 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
989 }
990}