1use std::{
2 iter::Sum as IterSum,
3 mem::MaybeUninit,
4 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5 sync::Arc,
6};
7
8use serde::{Deserialize, Serialize};
9use subtle::{Choice, ConstantTimeEq};
10use typenum::{Prod, Sum, U1, U2, U3};
11use wincode::{
12 io::{Reader, Writer},
13 ReadResult,
14 SchemaRead,
15 SchemaWrite,
16 WriteResult,
17};
18
19use crate::{
20 algebra::{
21 elliptic_curve::{BaseField, Curve, Point, ScalarAsExtension, ScalarField},
22 field::{FieldElement, FieldExtension},
23 },
24 random::{CryptoRngCore, Random, RandomWith},
25 types::{
26 heap_array::{CurvePoints, FieldElements},
27 ConditionallySelectable,
28 HeapArray,
29 Positive,
30 },
31};
32
33pub type GlobalKey<A> = Arc<A>;
41
42pub type GlobalFieldKey<F> = Arc<FieldElement<F>>;
44pub type GlobalScalarKey<C> = GlobalFieldKey<ScalarField<C>>;
46pub type GlobalBaseKey<C> = GlobalFieldKey<BaseField<C>>;
48pub type GlobalCurveKey<C> = GlobalFieldKey<ScalarField<C>>;
51
52#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
65#[repr(C)]
66pub struct PairwiseAuthKey<A, B> {
67 pub alpha: GlobalKey<A>, pub beta: B, }
70
71impl<A: std::fmt::Debug, B: std::fmt::Debug> std::fmt::Debug for PairwiseAuthKey<A, B> {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 f.debug_struct("PairwiseAuthKey")
74 .field("alpha", &self.alpha)
75 .field("beta", &self.beta)
76 .finish()
77 }
78}
79
80impl<A, B> PairwiseAuthKey<A, B> {
81 #[inline]
83 pub fn new(alpha: Arc<A>, beta: B) -> Self {
84 PairwiseAuthKey { alpha, beta }
85 }
86
87 #[inline]
89 pub fn get_beta(&self) -> &B {
90 &self.beta
91 }
92
93 #[inline]
95 pub fn get_alpha(&self) -> &A {
96 &self.alpha
97 }
98
99 #[inline]
101 pub fn alpha(&self) -> Arc<A> {
102 self.alpha.clone()
103 }
104}
105
106pub type FieldKey<F> = PairwiseAuthKey<FieldElement<F>, FieldElement<F>>;
114
115pub type ScalarKey<C> = FieldKey<ScalarField<C>>;
118pub type BaseFieldKey<C> = FieldKey<BaseField<C>>;
120
121pub type FieldKeys<F, M> = PairwiseAuthKey<FieldElement<F>, FieldElements<F, M>>;
127
128pub type ScalarKeys<C, M> = FieldKeys<ScalarField<C>, M>;
130pub type BaseFieldKeys<C, M> = FieldKeys<BaseField<C>, M>;
132
133pub type CurveKey<C> = PairwiseAuthKey<ScalarAsExtension<C>, Point<C>>;
135pub type CurveKeys<C, M> = PairwiseAuthKey<ScalarAsExtension<C>, CurvePoints<C, M>>;
137
138#[macros::op_variants(owned, borrowed, flipped)]
143impl<A: PartialEq, B> Add<&PairwiseAuthKey<A, B>> for PairwiseAuthKey<A, B>
144where
145 for<'a> B: Add<&'a B, Output = B>,
146{
147 type Output = PairwiseAuthKey<A, B>;
148
149 #[inline]
150 fn add(mut self, other: &PairwiseAuthKey<A, B>) -> Self::Output {
151 assert!(self.alpha == other.alpha, "alpha mismatch");
152 self.beta = self.beta + &other.beta;
153 self
154 }
155}
156
157#[macros::op_variants(owned)]
158impl<'a, A: PartialEq, B> AddAssign<&'a PairwiseAuthKey<A, B>> for PairwiseAuthKey<A, B>
159where
160 for<'b> B: AddAssign<&'b B>,
161{
162 #[inline]
163 fn add_assign(&mut self, other: &'a PairwiseAuthKey<A, B>) {
164 assert!(self.alpha == other.alpha, "alpha mismatch");
165 self.beta += &other.beta;
166 }
167}
168
169#[macros::op_variants(owned, borrowed, flipped)]
170impl<A: PartialEq, B> Sub<&PairwiseAuthKey<A, B>> for PairwiseAuthKey<A, B>
171where
172 for<'a> B: Sub<&'a B, Output = B>,
173{
174 type Output = PairwiseAuthKey<A, B>;
175
176 #[inline]
177 fn sub(self, other: &PairwiseAuthKey<A, B>) -> Self::Output {
178 assert!(self.alpha == other.alpha, "alpha mismatch");
179 PairwiseAuthKey {
180 alpha: self.alpha,
181 beta: self.beta - &other.beta,
182 }
183 }
184}
185
186#[macros::op_variants(owned)]
187impl<'a, A: PartialEq, B> SubAssign<&'a PairwiseAuthKey<A, B>> for PairwiseAuthKey<A, B>
188where
189 for<'b> B: SubAssign<&'b B>,
190{
191 #[inline]
192 fn sub_assign(&mut self, other: &'a PairwiseAuthKey<A, B>) {
193 assert!(self.alpha == other.alpha, "alpha mismatch");
194 self.beta -= &other.beta;
195 }
196}
197
198#[macros::op_variants(borrowed)]
199impl<A, B: Neg<Output = B>> Neg for PairwiseAuthKey<A, B> {
200 type Output = PairwiseAuthKey<A, B>;
201
202 #[inline]
203 fn neg(mut self) -> Self::Output {
204 self.beta = -self.beta;
205 self
206 }
207}
208
209impl<A: Default + PartialEq, B: Default> IterSum for PairwiseAuthKey<A, B>
210where
211 for<'a> B: Add<&'a B, Output = B>,
212{
213 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
214 let first = iter.next().unwrap_or_default();
215 iter.fold(first, |acc, x| acc + &x)
216 }
217}
218
219impl<A, B, RHS, BPrime> Mul<RHS> for PairwiseAuthKey<A, B>
224where
225 B: Mul<RHS, Output = BPrime>,
226{
227 type Output = PairwiseAuthKey<A, BPrime>;
228 #[inline]
229 fn mul(self, other: RHS) -> Self::Output {
230 PairwiseAuthKey {
231 alpha: self.alpha,
232 beta: self.beta * other,
233 }
234 }
235}
236
237impl<A: Clone, B, RHS, BPrime> Mul<RHS> for &PairwiseAuthKey<A, B>
238where
239 for<'b> &'b B: Mul<RHS, Output = BPrime>,
240{
241 type Output = PairwiseAuthKey<A, BPrime>;
242 #[inline]
243 fn mul(self, other: RHS) -> Self::Output {
244 PairwiseAuthKey {
245 alpha: self.alpha.clone(),
246 beta: &self.beta * other,
247 }
248 }
249}
250
251impl<A, B, RHS> MulAssign<RHS> for PairwiseAuthKey<A, B>
252where
253 B: MulAssign<RHS>,
254{
255 #[inline]
256 fn mul_assign(&mut self, other: RHS) {
257 self.beta *= other;
258 }
259}
260
261impl<A: Random, B: Random> Random for PairwiseAuthKey<A, B> {
266 fn random(mut rng: impl CryptoRngCore) -> Self {
267 PairwiseAuthKey {
268 alpha: A::random(&mut rng).into(),
269 beta: B::random(&mut rng),
270 }
271 }
272}
273
274impl<A: Clone, B: Random> RandomWith<GlobalKey<A>> for PairwiseAuthKey<A, B> {
275 fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalKey<A>) -> Self {
276 PairwiseAuthKey {
277 alpha,
278 beta: B::random(&mut rng),
279 }
280 }
281}
282
283impl<A: ConstantTimeEq, B: ConstantTimeEq> ConstantTimeEq for PairwiseAuthKey<A, B> {
288 #[inline]
289 fn ct_eq(&self, other: &Self) -> Choice {
290 self.alpha.ct_eq(&other.alpha) & self.beta.ct_eq(&other.beta)
291 }
292}
293
294impl<A: ConditionallySelectable, B: ConditionallySelectable> ConditionallySelectable
295 for PairwiseAuthKey<A, B>
296{
297 #[inline]
298 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
299 PairwiseAuthKey {
300 alpha: A::conditional_select(&a.alpha, &b.alpha, choice).into(),
301 beta: B::conditional_select(&a.beta, &b.beta, choice),
302 }
303 }
304}
305
306impl<A: SchemaWrite<Src = A>, B: SchemaWrite<Src = B>> SchemaWrite for PairwiseAuthKey<A, B> {
311 type Src = Self;
312
313 fn size_of(src: &Self::Src) -> WriteResult<usize> {
314 Ok(A::size_of(&src.alpha)? + B::size_of(&src.beta)?)
315 }
316
317 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
318 A::write(writer, &src.alpha)?;
319 B::write(writer, &src.beta)
320 }
321}
322
323impl<'de, A: SchemaRead<'de, Dst = A>, B: SchemaRead<'de, Dst = B>> SchemaRead<'de>
324 for PairwiseAuthKey<A, B>
325{
326 type Dst = Self;
327
328 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
329 let mut alpha_uninit = MaybeUninit::<A>::uninit();
330 let mut beta_uninit = MaybeUninit::<B>::uninit();
331 A::read(reader, &mut alpha_uninit)?;
332 B::read(reader, &mut beta_uninit)?;
333 let alpha = unsafe { alpha_uninit.assume_init() }.into();
335 let beta = unsafe { beta_uninit.assume_init() };
336 dst.write(PairwiseAuthKey { alpha, beta });
337 Ok(())
338 }
339}
340
341impl<A: Clone, B: Copy, M: Positive> PairwiseAuthKey<A, HeapArray<B, M>> {
348 #[allow(clippy::type_complexity)]
349 pub fn split<M1, M2>(
353 self,
354 ) -> (
355 PairwiseAuthKey<A, HeapArray<B, M1>>,
356 PairwiseAuthKey<A, HeapArray<B, M2>>,
357 )
358 where
359 M1: Positive,
360 M2: Positive + Add<M1, Output = M>,
361 {
362 let PairwiseAuthKey { alpha, beta } = self;
363 let (betas1, betas2) = beta.split::<M1, M2>();
364 (
365 PairwiseAuthKey::new(alpha.clone(), betas1),
366 PairwiseAuthKey::new(alpha, betas2),
367 )
368 }
369
370 pub fn split_last_pos<M1>(self) -> (PairwiseAuthKey<A, HeapArray<B, M1>>, PairwiseAuthKey<A, B>)
371 where
372 M1: Positive + Add<typenum::B1, Output = M>,
373 {
374 let PairwiseAuthKey { alpha, beta } = self;
375 let (betas1, beta2) = beta.split_last_pos();
376 (
377 PairwiseAuthKey::new(alpha.clone(), betas1),
378 PairwiseAuthKey::new(alpha, beta2),
379 )
380 }
381
382 #[allow(clippy::type_complexity)]
383 pub fn split_halves<MDiv2>(
387 self,
388 ) -> (
389 PairwiseAuthKey<A, HeapArray<B, MDiv2>>,
390 PairwiseAuthKey<A, HeapArray<B, MDiv2>>,
391 )
392 where
393 MDiv2: Positive + Mul<U2, Output = M>,
394 {
395 let PairwiseAuthKey { alpha, beta } = self;
396 let (betas1, betas2) = beta.split_halves::<MDiv2>();
397 (
398 PairwiseAuthKey::new(alpha.clone(), betas1),
399 PairwiseAuthKey::new(alpha, betas2),
400 )
401 }
402
403 pub fn merge_halves(this: Self, other: Self) -> PairwiseAuthKey<A, HeapArray<B, Prod<M, U2>>>
407 where
408 M: Positive + Mul<U2, Output: Positive>,
409 A: PartialEq,
410 {
411 assert!(this.alpha == other.alpha, "alpha mismatch in merge_halves");
412 PairwiseAuthKey {
413 alpha: this.alpha,
414 beta: HeapArray::merge_halves(this.beta, other.beta),
415 }
416 }
417
418 #[allow(clippy::type_complexity)]
419 pub fn split3<M1, M2, M3>(
423 self,
424 ) -> (
425 PairwiseAuthKey<A, HeapArray<B, M1>>,
426 PairwiseAuthKey<A, HeapArray<B, M2>>,
427 PairwiseAuthKey<A, HeapArray<B, M3>>,
428 )
429 where
430 M1: Positive,
431 M2: Positive + Add<M1>,
432 M3: Positive + Add<Sum<M2, M1>, Output = M>,
433 {
434 let PairwiseAuthKey { alpha, beta } = self;
435 let (betas1, betas2, betas3) = beta.split3::<M1, M2, M3>();
436 (
437 PairwiseAuthKey::new(alpha.clone(), betas1),
438 PairwiseAuthKey::new(alpha.clone(), betas2),
439 PairwiseAuthKey::new(alpha, betas3),
440 )
441 }
442
443 #[allow(clippy::type_complexity)]
444 pub fn split_thirds<MDiv3>(
448 self,
449 ) -> (
450 PairwiseAuthKey<A, HeapArray<B, MDiv3>>,
451 PairwiseAuthKey<A, HeapArray<B, MDiv3>>,
452 PairwiseAuthKey<A, HeapArray<B, MDiv3>>,
453 )
454 where
455 MDiv3: Positive + Mul<U3, Output = M>,
456 {
457 let PairwiseAuthKey { alpha, beta } = self;
458 let (betas1, betas2, betas3) = beta.split_thirds::<MDiv3>();
459 (
460 PairwiseAuthKey::new(alpha.clone(), betas1),
461 PairwiseAuthKey::new(alpha.clone(), betas2),
462 PairwiseAuthKey::new(alpha, betas3),
463 )
464 }
465
466 pub fn merge_thirds(
470 first: Self,
471 second: Self,
472 third: Self,
473 ) -> PairwiseAuthKey<A, HeapArray<B, Prod<M, U3>>>
474 where
475 M: Positive + Mul<U3, Output: Positive>,
476 A: PartialEq,
477 {
478 assert!(
479 first.alpha == second.alpha,
480 "alpha mismatch in merge_thirds"
481 );
482 assert!(first.alpha == third.alpha, "alpha mismatch in merge_thirds");
483 PairwiseAuthKey {
484 alpha: first.alpha,
485 beta: HeapArray::merge_thirds(first.beta, second.beta, third.beta),
486 }
487 }
488}
489
490impl<A, T> From<PairwiseAuthKey<A, T>> for PairwiseAuthKey<A, HeapArray<T, U1>> {
498 fn from(key: PairwiseAuthKey<A, T>) -> Self {
499 PairwiseAuthKey {
500 alpha: key.alpha,
501 beta: HeapArray::from(key.beta),
502 }
503 }
504}
505
506pub struct FieldShareKeysIterator<F: FieldExtension, M: Positive> {
507 keys: FieldKeys<F, M>,
508 index: usize,
509}
510
511impl<F: FieldExtension, M: Positive> Iterator for FieldShareKeysIterator<F, M> {
512 type Item = FieldKey<F>;
513
514 fn next(&mut self) -> Option<Self::Item> {
515 if self.index < M::to_usize() {
516 let key = PairwiseAuthKey {
517 alpha: self.keys.alpha.clone(),
518 beta: self.keys.beta[self.index],
519 };
520 self.index += 1;
521 Some(key)
522 } else {
523 None
524 }
525 }
526}
527
528impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldShareKeysIterator<F, M> {
529 fn len(&self) -> usize {
530 M::to_usize()
531 }
532}
533
534impl<F: FieldExtension, M: Positive> IntoIterator for FieldKeys<F, M> {
535 type Item = FieldKey<F>;
536 type IntoIter = FieldShareKeysIterator<F, M>;
537
538 fn into_iter(self) -> Self::IntoIter {
539 FieldShareKeysIterator::<F, M> {
540 keys: self,
541 index: 0,
542 }
543 }
544}
545
546pub struct FieldShareKeyRef<'a, F>
547where
548 F: FieldExtension,
549{
550 pub alpha: GlobalFieldKey<F>,
551 pub beta: &'a FieldElement<F>,
552}
553
554impl<'a, F: FieldExtension> From<FieldShareKeyRef<'a, F>> for FieldKey<F> {
555 fn from(val: FieldShareKeyRef<'a, F>) -> Self {
556 PairwiseAuthKey {
557 alpha: val.alpha,
558 beta: *val.beta,
559 }
560 }
561}
562
563pub struct FieldShareKeysRefIterator<'a, F, M>
564where
565 F: FieldExtension,
566 M: Positive,
567{
568 keys: &'a FieldKeys<F, M>,
569 index: usize,
570}
571
572impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldShareKeysRefIterator<'_, F, M> {
573 fn len(&self) -> usize {
574 M::to_usize()
575 }
576}
577
578impl<'a, F: FieldExtension, M: Positive> Iterator for FieldShareKeysRefIterator<'a, F, M> {
579 type Item = FieldShareKeyRef<'a, F>;
580
581 fn next(&mut self) -> Option<Self::Item> {
582 if self.index < M::to_usize() {
583 let key = FieldShareKeyRef {
584 alpha: self.keys.alpha.clone(),
585 beta: &self.keys.beta[self.index],
586 };
587 self.index += 1;
588 Some(key)
589 } else {
590 None
591 }
592 }
593}
594
595impl<'a, F: FieldExtension, M: Positive> IntoIterator for &'a FieldKeys<F, M> {
596 type Item = FieldShareKeyRef<'a, F>;
597 type IntoIter = FieldShareKeysRefIterator<'a, F, M>;
598
599 fn into_iter(self) -> Self::IntoIter {
600 FieldShareKeysRefIterator {
601 keys: self,
602 index: 0,
603 }
604 }
605}
606
607impl<C: Curve> From<ScalarKey<C>> for CurveKey<C> {
610 #[inline]
611 fn from(scalar_key: ScalarKey<C>) -> Self {
612 PairwiseAuthKey {
613 alpha: scalar_key.alpha,
614 beta: scalar_key.beta * Point::<C>::generator(),
615 }
616 }
617}
618
619impl<C: Curve, M: Positive> From<ScalarKeys<C, M>> for CurveKeys<C, M> {
620 #[inline]
621 fn from(scalar_key: ScalarKeys<C, M>) -> Self {
622 PairwiseAuthKey {
623 alpha: scalar_key.alpha,
624 beta: scalar_key.beta * &Point::<C>::generator(),
625 }
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use typenum::{U10, U8};
632
633 use super::*;
634 use crate::algebra::elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension};
635
636 type Fq = ScalarAsExtension<C>;
637
638 #[test]
639 fn test_addition() {
640 let alpha = GlobalFieldKey::new(Fq::from(3u32));
641 let key1 = PairwiseAuthKey {
642 alpha: alpha.clone(),
643 beta: Fq::from(10u32),
644 };
645 let key2 = PairwiseAuthKey {
646 alpha: alpha.clone(),
647 beta: Fq::from(7u32),
648 };
649 let expected_result = PairwiseAuthKey {
650 alpha,
651 beta: Fq::from(17u32),
652 };
653 assert_eq!(key1 + key2, expected_result);
654 }
655
656 #[test]
657 fn test_subtraction() {
658 let alpha = GlobalFieldKey::new(Fq::from(3u32));
659 let key1 = PairwiseAuthKey {
660 alpha: alpha.clone(),
661 beta: Fq::from(10u32),
662 };
663 let key2 = PairwiseAuthKey {
664 alpha: alpha.clone(),
665 beta: Fq::from(7u32),
666 };
667 let expected_result = PairwiseAuthKey {
668 alpha,
669 beta: Fq::from(3u32),
670 };
671 assert_eq!(key1 - key2, expected_result);
672 }
673
674 #[test]
675 fn test_multiplication() {
676 let alpha = GlobalFieldKey::new(Fq::from(3u32));
677 let key = PairwiseAuthKey {
678 alpha: alpha.clone(),
679 beta: Fq::from(10u32),
680 };
681 let scalar = Fq::from(3u32);
682 let expected_result = PairwiseAuthKey {
683 alpha,
684 beta: Fq::from(30u32),
685 };
686 assert_eq!(key * scalar, expected_result);
687 }
688
689 #[test]
690 fn test_negation() {
691 let key = PairwiseAuthKey {
692 alpha: GlobalFieldKey::new(Fq::from(5u32)),
693 beta: Fq::from(10u32),
694 };
695 let expected_result = PairwiseAuthKey {
696 alpha: GlobalFieldKey::new(Fq::from(5u32)),
697 beta: -Fq::from(10u32),
698 };
699 assert_eq!(-key, expected_result);
700 }
701
702 #[test]
703 fn test_batched_addition() {
704 let alpha = GlobalFieldKey::new(Fq::from(3u32));
705 let key1 = PairwiseAuthKey {
706 alpha: alpha.clone(),
707 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(10u32)),
708 };
709 let key2 = PairwiseAuthKey {
710 alpha: alpha.clone(),
711 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(7u32)),
712 };
713 let expected_result = PairwiseAuthKey {
714 alpha,
715 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(17u32)),
716 };
717 assert_eq!(key1 + key2, expected_result);
718 }
719
720 #[test]
721 fn test_batched_subtraction() {
722 let alpha = GlobalFieldKey::new(Fq::from(3u32));
723 let key1 = PairwiseAuthKey {
724 alpha: alpha.clone(),
725 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(10u32)),
726 };
727 let key2 = PairwiseAuthKey {
728 alpha: alpha.clone(),
729 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(7u32)),
730 };
731 let expected_result = PairwiseAuthKey {
732 alpha,
733 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(3u32)),
734 };
735 assert_eq!(key1 - key2, expected_result);
736 }
737
738 #[test]
739 fn test_batched_multiplication() {
740 let alpha = GlobalFieldKey::new(Fq::from(3u32));
741 let key = PairwiseAuthKey {
742 alpha: alpha.clone(),
743 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(10u32)),
744 };
745 let scalar = Fq::from(3u32);
746 let expected_result = PairwiseAuthKey {
747 alpha,
748 beta: HeapArray::<_, U10>::from_fn(|_| Fq::from(30u32)),
749 };
750 assert_eq!(key * &scalar, expected_result);
751 }
752
753 #[test]
754 fn test_batched_negation() {
755 let key = PairwiseAuthKey {
756 alpha: GlobalFieldKey::new(Fq::from(5u32)),
757 beta: HeapArray::<_, U8>::from_fn(|_| Fq::from(10u32)),
758 };
759 let expected_result = PairwiseAuthKey {
760 alpha: GlobalFieldKey::new(Fq::from(5u32)),
761 beta: -HeapArray::<_, U8>::from_fn(|_| Fq::from(10u32)),
762 };
763 assert_eq!(-key, expected_result);
764 }
765
766 mod curve_single {
769 use super::*;
770 use crate::algebra::elliptic_curve::Curve25519Ristretto as C;
771
772 type P = Point<C>;
773 type FrExt = ScalarAsExtension<C>;
774
775 #[test]
776 fn test_addition() {
777 let mut rng = rand::thread_rng();
778 let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
779 let beta1 = P::random(&mut rng);
780 let beta2 = P::random(&mut rng);
781 let key1 = CurveKey {
782 alpha: alpha.clone(),
783 beta: beta1,
784 };
785 let key2 = CurveKey {
786 alpha: alpha.clone(),
787 beta: beta2,
788 };
789 let expected = CurveKey {
790 alpha,
791 beta: beta1 + beta2,
792 };
793 assert_eq!(key1 + key2, expected);
794 }
795
796 #[test]
797 fn test_subtraction() {
798 let mut rng = rand::thread_rng();
799 let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
800 let beta1 = P::random(&mut rng);
801 let beta2 = P::random(&mut rng);
802 let key1 = CurveKey {
803 alpha: alpha.clone(),
804 beta: beta1,
805 };
806 let key2 = CurveKey {
807 alpha: alpha.clone(),
808 beta: beta2,
809 };
810 let expected = CurveKey {
811 alpha,
812 beta: beta1 - beta2,
813 };
814 assert_eq!(key1 - key2, expected);
815 }
816
817 #[test]
818 fn test_multiplication() {
819 let mut rng = rand::thread_rng();
820 let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
821 let beta1 = P::random(&mut rng);
822 let key = CurveKey {
823 alpha: alpha.clone(),
824 beta: beta1,
825 };
826 let scalar = FrExt::from(3u32);
827 let expected = CurveKey {
828 alpha,
829 beta: beta1 * scalar,
830 };
831 assert_eq!(key * scalar, expected);
832 }
833
834 #[test]
835 fn test_negation() {
836 let mut rng = rand::thread_rng();
837 let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
838 let beta1 = P::random(&mut rng);
839 let key = CurveKey {
840 alpha: alpha.clone(),
841 beta: beta1,
842 };
843 let expected = CurveKey {
844 alpha,
845 beta: -beta1,
846 };
847 assert_eq!(-key, expected);
848 }
849 }
850
851 mod curve_batched {
854 use typenum::U8;
855
856 use super::*;
857 use crate::{
858 algebra::elliptic_curve::Curve25519Ristretto as C,
859 random::{self, Random},
860 types::heap_array::CurvePoints,
861 };
862
863 type FrExt = ScalarAsExtension<C>;
864 type Ps = CurvePoints<C, U8>;
865
866 #[test]
867 fn test_addition() {
868 let mut rng = random::test_rng();
869 let alpha = GlobalCurveKey::<C>::random(&mut rng);
870 let beta1 = Ps::random(&mut rng);
871 let beta2 = Ps::random(&mut rng);
872 let key1 = CurveKeys {
873 alpha: alpha.clone(),
874 beta: beta1.clone(),
875 };
876 let key2 = CurveKeys {
877 alpha: alpha.clone(),
878 beta: beta2.clone(),
879 };
880 let expected = CurveKeys {
881 alpha,
882 beta: beta1 + beta2,
883 };
884 assert_eq!(key1 + key2, expected);
885 }
886
887 #[test]
888 fn test_subtraction() {
889 let mut rng = random::test_rng();
890 let alpha = GlobalCurveKey::<C>::random(&mut rng);
891 let beta1 = Ps::random(&mut rng);
892 let beta2 = Ps::random(&mut rng);
893 let key1 = CurveKeys {
894 alpha: alpha.clone(),
895 beta: beta1.clone(),
896 };
897 let key2 = CurveKeys {
898 alpha: alpha.clone(),
899 beta: beta2.clone(),
900 };
901 let expected = CurveKeys {
902 alpha,
903 beta: beta1 - beta2,
904 };
905 assert_eq!(key1 - key2, expected);
906 }
907
908 #[test]
909 fn test_multiplication() {
910 let mut rng = random::test_rng();
911 let alpha = GlobalCurveKey::<C>::random(&mut rng);
912 let beta1 = Ps::random(&mut rng);
913 let key = CurveKeys {
914 alpha: alpha.clone(),
915 beta: beta1.clone(),
916 };
917 let scalar = FrExt::from(3u32);
918 let expected = CurveKeys {
919 alpha,
920 beta: beta1 * &scalar,
921 };
922 assert_eq!(key * &scalar, expected);
923 }
924
925 #[test]
926 fn test_negation() {
927 let mut rng = random::test_rng();
928 let alpha = GlobalCurveKey::<C>::random(&mut rng);
929 let beta1 = Ps::random(&mut rng);
930 let key = CurveKeys {
931 alpha: alpha.clone(),
932 beta: beta1.clone(),
933 };
934 let expected = CurveKeys {
935 alpha,
936 beta: -beta1,
937 };
938 assert_eq!(-key, expected);
939 }
940 }
941}