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