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