1use crate::ed25519::Fq;
2use crate::ed25519::Fr;
3use crate::{Coordinates, CurveAffine, CurveAffineExt, CurveExt};
4use core::cmp;
5use core::fmt::Debug;
6use core::iter::Sum;
7use core::ops::{Add, Mul, Neg, Sub};
8use ff::{BatchInverter, Field, PrimeField};
9use group::{self, Curve};
10use group::{prime::PrimeCurveAffine, GroupEncoding};
11use rand::RngCore;
12use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
13
14#[cfg(feature = "derive_serde")]
15use serde::{Deserialize, Serialize};
16
17const ED25519_GENERATOR_X: Fq = Fq::from_raw([
18 0xc956_2d60_8f25_d51a,
19 0x692c_c760_9525_a7b2,
20 0xc0a4_e231_fdd6_dc5c,
21 0x2169_36d3_cd6e_53fe,
22]);
23const ED25519_GENERATOR_Y: Fq = Fq::from_raw([
24 0x6666_6666_6666_6658,
25 0x6666_6666_6666_6666,
26 0x6666_6666_6666_6666,
27 0x6666_6666_6666_6666,
28]);
29
30const ED25519_D: Fq = Fq::from_raw([
32 0x75eb_4dca_1359_78a3,
33 0x0070_0a4d_4141_d8ab,
34 0x8cc7_4079_7779_e898,
35 0x5203_6cee_2b6f_fe73,
36]);
37
38const FR_MODULUS_BYTES: [u8; 32] = [
39 237, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 16,
41];
42
43use crate::{
44 impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
45 impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
46};
47
48#[derive(Copy, Clone, Debug)]
49#[cfg_attr(feature = "derive_serde", derive(Serialize, Deserialize))]
50pub struct Ed25519 {
51 pub x: Fq,
52 pub y: Fq,
53 pub z: Fq,
54 pub t: Fq,
55}
56
57#[derive(Copy, Clone, Debug, PartialEq, Hash)]
58#[cfg_attr(feature = "derive_serde", derive(Serialize, Deserialize))]
59pub struct Ed25519Affine {
60 pub x: Fq,
61 pub y: Fq,
62}
63
64#[derive(Copy, Clone, Hash, Default)]
65pub struct Ed25519Compressed([u8; 32]);
66
67impl Ed25519 {
68 pub const fn identity() -> Self {
70 Ed25519 {
71 x: Fq::zero(),
72 y: Fq::one(),
73 z: Fq::one(),
74 t: Fq::zero(),
75 }
76 }
77
78 pub fn is_identity(&self) -> Choice {
80 self.x.ct_eq(&Fq::zero()) & self.y.ct_eq(&self.z)
84 }
85
86 pub fn is_torsion_free(&self) -> Choice {
89 self.multiply(&FR_MODULUS_BYTES).is_identity()
90 }
91
92 #[inline]
93 fn multiply(&self, by: &[u8; 32]) -> Ed25519 {
94 let zero = Ed25519::identity();
95 let mut acc = Ed25519::identity();
96
97 for bit in by
104 .iter()
105 .rev()
106 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
107 .skip(3)
108 {
109 acc = acc.double();
110 acc += Ed25519::conditional_select(&zero, self, bit);
111 }
112
113 acc
114 }
115
116 pub fn mul_by_cofactor(&self) -> Ed25519 {
118 self.double().double().double()
119 }
120
121 pub fn generator() -> Self {
122 let generator = Ed25519Affine::generator();
123 Self {
124 x: generator.x,
125 y: generator.y,
126 z: Fq::one(),
127 t: generator.x * generator.y,
128 }
129 }
130
131 pub fn double(&self) -> Ed25519 {
132 let a = self.x.square();
145 let b = self.y.square();
146 let c = self.z.square().double();
147
148 let h = a + b;
149 let e = h - (self.x + self.y).square();
150 let g = a - b;
151 let f = c + g;
152
153 Ed25519 {
154 x: e * f,
155 y: g * h,
156 z: f * g,
157 t: e * h,
158 }
159 }
160}
161
162impl Ed25519Affine {
163 pub const fn identity() -> Self {
165 Ed25519Affine {
166 x: Fq::zero(),
167 y: Fq::one(),
168 }
169 }
170
171 pub fn is_identity(&self) -> Choice {
173 Ed25519::from(*self).is_identity()
174 }
175
176 pub fn generator() -> Self {
177 Self {
178 x: ED25519_GENERATOR_X,
179 y: ED25519_GENERATOR_Y,
180 }
181 }
182
183 pub fn to_extended(&self) -> Ed25519 {
184 Ed25519 {
185 x: self.x,
186 y: self.y,
187 z: Fq::one(),
188 t: self.x * self.y,
189 }
190 }
191
192 pub fn random(mut rng: impl RngCore) -> Self {
193 loop {
194 let y = Fq::random(&mut rng);
195 let flip_sign = rng.next_u32() % 2 != 0;
196
197 let y2 = y.square();
198 let p = ((y2 - Fq::one())
199 * ((Fq::one() + ED25519_D * y2).invert().unwrap_or(Fq::zero())))
200 .sqrt()
201 .map(|x| Ed25519Affine {
202 x: if flip_sign { -x } else { x },
203 y,
204 });
205
206 if p.is_some().into() {
207 use crate::group::cofactor::CofactorGroup;
208 let p = p.unwrap().to_curve();
209
210 if bool::from(!p.is_identity()) {
211 return p.clear_cofactor().to_affine();
212 }
213 }
214 }
215 }
216
217 pub fn to_bytes(&self) -> [u8; 32] {
219 let mut tmp = self.y.to_bytes();
220 let u = self.x.to_bytes();
221
222 tmp[31] |= u[0] << 7;
225
226 tmp
227 }
228
229 pub fn from_bytes(b: [u8; 32]) -> CtOption<Self> {
233 Self::from_bytes_inner(b, 1.into())
234 }
235
236 fn from_bytes_inner(mut b: [u8; 32], zip_216_enabled: Choice) -> CtOption<Self> {
237 let sign = b[31] >> 7;
239
240 b[31] &= 0b0111_1111;
242
243 Fq::from_bytes(&b).and_then(|v| {
245 let v2 = v.square();
257
258 ((v2 - Fq::one()) * ((Fq::one() + ED25519_D * v2).invert().unwrap_or(Fq::zero())))
259 .sqrt()
260 .and_then(|u| {
261 let flip_sign = Choice::from((u.to_bytes()[0] ^ sign) & 1);
263 let u_negated = -u;
264 let final_u = Fq::conditional_select(&u, &u_negated, flip_sign);
265
266 let u_is_zero = u.ct_eq(&Fq::zero());
272 CtOption::new(
273 Ed25519Affine { x: final_u, y: v },
274 !(zip_216_enabled & u_is_zero & flip_sign),
275 )
276 })
277 })
278 }
279}
280
281impl std::fmt::Debug for Ed25519Compressed {
283 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
284 self.0[..].fmt(f)
285 }
286}
287
288impl AsRef<[u8]> for Ed25519Compressed {
289 fn as_ref(&self) -> &[u8] {
290 &self.0
291 }
292}
293
294impl AsMut<[u8]> for Ed25519Compressed {
295 fn as_mut(&mut self) -> &mut [u8] {
296 &mut self.0
297 }
298}
299
300impl<'a> From<&'a Ed25519Affine> for Ed25519 {
302 fn from(p: &'a Ed25519Affine) -> Ed25519 {
303 p.to_curve()
304 }
305}
306
307impl From<Ed25519Affine> for Ed25519 {
308 fn from(p: Ed25519Affine) -> Ed25519 {
309 p.to_curve()
310 }
311}
312
313impl Default for Ed25519 {
314 fn default() -> Ed25519 {
315 Ed25519::identity()
316 }
317}
318
319impl subtle::ConstantTimeEq for Ed25519 {
320 fn ct_eq(&self, other: &Self) -> Choice {
321 (self.x * other.z).ct_eq(&(other.x * self.z))
322 & (self.y * other.z).ct_eq(&(other.y * self.z))
323 }
324}
325
326impl subtle::ConditionallySelectable for Ed25519 {
327 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
328 Ed25519 {
329 x: Fq::conditional_select(&a.x, &b.x, choice),
330 y: Fq::conditional_select(&a.y, &b.y, choice),
331 z: Fq::conditional_select(&a.z, &b.z, choice),
332 t: Fq::conditional_select(&a.t, &b.t, choice),
333 }
334 }
335}
336
337impl PartialEq for Ed25519 {
338 fn eq(&self, other: &Self) -> bool {
339 self.ct_eq(other).into()
340 }
341}
342
343impl cmp::Eq for Ed25519 {}
344
345impl CurveExt for Ed25519 {
346 type ScalarExt = Fr;
347 type Base = Fq;
348 type AffineExt = Ed25519Affine;
349
350 const CURVE_ID: &'static str = "ed25519";
351
352 fn is_on_curve(&self) -> Choice {
353 let affine = Ed25519Affine::from(*self);
354 !self.z.is_zero() & affine.is_on_curve() & (affine.x * affine.y * self.z).ct_eq(&self.t)
355 }
356
357 fn endo(&self) -> Self {
358 unimplemented!();
359 }
360
361 fn jacobian_coordinates(&self) -> (Fq, Fq, Fq) {
362 unimplemented!();
363 }
364
365 fn hash_to_curve<'a>(_: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
366 unimplemented!();
367 }
368
369 fn a() -> Self::Base {
370 unimplemented!()
371 }
372
373 fn b() -> Self::Base {
374 unimplemented!()
375 }
376
377 fn new_jacobian(_x: Self::Base, _y: Self::Base, _z: Self::Base) -> CtOption<Self> {
378 unimplemented!();
379 }
380}
381
382impl group::Curve for Ed25519 {
383 type AffineRepr = Ed25519Affine;
384
385 fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) {
386 assert_eq!(p.len(), q.len());
387
388 for (p, q) in p.iter().zip(q.iter_mut()) {
389 q.x = p.z;
392 }
393
394 BatchInverter::invert_with_internal_scratch(q, |q| &mut q.x, |q| &mut q.y);
395
396 for (p, q) in p.iter().zip(q.iter_mut()).rev() {
397 let tmp = q.x;
398
399 q.x = p.x * tmp; q.y = p.y * tmp; }
403 }
404
405 fn to_affine(&self) -> Self::AffineRepr {
406 let zinv = self.z.invert().unwrap();
409
410 Ed25519Affine {
411 x: self.x * zinv,
412 y: self.y * zinv,
413 }
414 }
415}
416
417impl group::Group for Ed25519 {
418 type Scalar = Fr;
419
420 fn random(mut rng: impl RngCore) -> Self {
421 Ed25519Affine::random(&mut rng).to_curve()
422 }
423
424 fn generator() -> Self {
425 Ed25519::generator()
426 }
427
428 fn identity() -> Self {
429 Self::identity()
430 }
431
432 fn is_identity(&self) -> Choice {
433 self.is_identity()
434 }
435
436 #[must_use]
437 fn double(&self) -> Self {
438 self.double()
439 }
440}
441
442impl GroupEncoding for Ed25519 {
443 type Repr = Ed25519Compressed;
444
445 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
446 Ed25519Affine::from_bytes(bytes.0).map(Self::from)
447 }
448
449 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
450 Ed25519Affine::from_bytes(bytes.0).map(Self::from)
451 }
452
453 fn to_bytes(&self) -> Self::Repr {
454 Ed25519Compressed(Ed25519Affine::from(self).to_bytes())
455 }
456}
457
458impl crate::serde::SerdeObject for Ed25519 {
459 fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
460 debug_assert_eq!(bytes.len(), 4 * Fq::size());
461 let [x, y, z, t] = [0, 1, 2, 3]
462 .map(|i| Fq::from_raw_bytes_unchecked(&bytes[i * Fq::size()..(i + 1) * Fq::size()]));
463 Self { x, y, z, t }
464 }
465 fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
466 if bytes.len() != 4 * Fq::size() {
467 return None;
468 }
469 let [x, y, z, t] =
470 [0, 1, 2, 3].map(|i| Fq::from_raw_bytes(&bytes[i * Fq::size()..(i + 1) * Fq::size()]));
471 x.zip(y).zip(z).zip(t).and_then(|(((x, y), z), t)| {
472 let res = Self { x, y, z, t };
473 bool::from(res.is_on_curve()).then_some(res)
475 })
476 }
477 fn to_raw_bytes(&self) -> Vec<u8> {
478 let mut res = Vec::with_capacity(4 * Fq::size());
479 Self::write_raw(self, &mut res).unwrap();
480 res
481 }
482 fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
483 let [x, y, z, t] = [(); 4].map(|_| Fq::read_raw_unchecked(reader));
484 Self { x, y, z, t }
485 }
486 fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
487 let x = Fq::read_raw(reader)?;
488 let y = Fq::read_raw(reader)?;
489 let z = Fq::read_raw(reader)?;
490 let t = Fq::read_raw(reader)?;
491 Ok(Self { x, y, z, t })
492 }
493 fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
494 self.x.write_raw(writer)?;
495 self.y.write_raw(writer)?;
496 self.z.write_raw(writer)?;
497 self.t.write_raw(writer)
498 }
499}
500
501impl group::prime::PrimeGroup for Ed25519 {}
502
503impl group::prime::PrimeCurve for Ed25519 {
504 type Affine = Ed25519Affine;
505}
506
507impl group::cofactor::CofactorCurve for Ed25519 {
508 type Affine = Ed25519Affine;
509}
510
511impl group::cofactor::CofactorGroup for Ed25519 {
512 type Subgroup = Ed25519;
513
514 fn clear_cofactor(&self) -> Self {
515 self.mul_by_cofactor()
516 }
517
518 fn into_subgroup(self) -> CtOption<Self::Subgroup> {
519 CtOption::new(self, self.is_torsion_free())
520 }
521
522 fn is_torsion_free(&self) -> Choice {
523 self.is_torsion_free()
524 }
525}
526
527impl<'a> From<&'a Ed25519> for Ed25519Affine {
528 fn from(p: &'a Ed25519) -> Ed25519Affine {
529 p.to_affine()
530 }
531}
532
533impl From<Ed25519> for Ed25519Affine {
534 fn from(p: Ed25519) -> Ed25519Affine {
535 p.to_affine()
536 }
537}
538
539impl Default for Ed25519Affine {
540 fn default() -> Ed25519Affine {
541 Ed25519Affine::identity()
542 }
543}
544
545impl subtle::ConstantTimeEq for Ed25519Affine {
546 fn ct_eq(&self, other: &Self) -> Choice {
547 self.x.ct_eq(&other.x) & self.y.ct_eq(&other.y)
548 }
549}
550
551impl subtle::ConditionallySelectable for Ed25519Affine {
552 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
553 Ed25519Affine {
554 x: Fq::conditional_select(&a.x, &b.x, choice),
555 y: Fq::conditional_select(&a.y, &b.y, choice),
556 }
557 }
558}
559
560impl cmp::Eq for Ed25519Affine {}
561
562impl group::GroupEncoding for Ed25519Affine {
563 type Repr = [u8; 32];
564
565 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
566 Self::from_bytes(*bytes)
567 }
568
569 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
570 Self::from_bytes(*bytes)
571 }
572
573 fn to_bytes(&self) -> Self::Repr {
574 self.to_bytes()
575 }
576}
577
578impl crate::serde::SerdeObject for Ed25519Affine {
579 fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
580 debug_assert_eq!(bytes.len(), 2 * Fq::size());
581 let [x, y] =
582 [0, Fq::size()].map(|i| Fq::from_raw_bytes_unchecked(&bytes[i..i + Fq::size()]));
583 Self { x, y }
584 }
585 fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
586 if bytes.len() != 2 * Fq::size() {
587 return None;
588 }
589 let [x, y] = [0, Fq::size()].map(|i| Fq::from_raw_bytes(&bytes[i..i + Fq::size()]));
590 x.zip(y).and_then(|(x, y)| {
591 let res = Self { x, y };
592 bool::from(res.is_on_curve()).then_some(res)
594 })
595 }
596 fn to_raw_bytes(&self) -> Vec<u8> {
597 let mut res = Vec::with_capacity(2 * Fq::size());
598 Self::write_raw(self, &mut res).unwrap();
599 res
600 }
601 fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
602 let [x, y] = [(); 2].map(|_| Fq::read_raw_unchecked(reader));
603 Self { x, y }
604 }
605 fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
606 let x = Fq::read_raw(reader)?;
607 let y = Fq::read_raw(reader)?;
608 Ok(Self { x, y })
609 }
610 fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
611 self.x.write_raw(writer)?;
612 self.y.write_raw(writer)
613 }
614}
615
616impl group::prime::PrimeCurveAffine for Ed25519Affine {
617 type Curve = Ed25519;
618 type Scalar = Fr;
619
620 fn generator() -> Self {
621 Ed25519Affine::generator()
622 }
623
624 fn identity() -> Self {
625 Ed25519Affine::identity()
626 }
627
628 fn is_identity(&self) -> Choice {
629 self.is_identity()
630 }
631
632 fn to_curve(&self) -> Self::Curve {
633 Ed25519 {
634 x: self.x,
635 y: self.y,
636 z: Fq::one(),
637 t: self.x * self.y,
638 }
639 }
640}
641
642impl group::cofactor::CofactorCurveAffine for Ed25519Affine {
643 type Curve = Ed25519;
644 type Scalar = Fr;
645
646 fn identity() -> Self {
647 <Self as group::prime::PrimeCurveAffine>::identity()
648 }
649
650 fn generator() -> Self {
651 <Self as group::prime::PrimeCurveAffine>::generator()
652 }
653
654 fn is_identity(&self) -> Choice {
655 <Self as group::prime::PrimeCurveAffine>::is_identity(self)
656 }
657
658 fn to_curve(&self) -> Self::Curve {
659 <Self as group::prime::PrimeCurveAffine>::to_curve(self)
660 }
661}
662
663impl CurveAffine for Ed25519Affine {
664 type ScalarExt = Fr;
665 type Base = Fq;
666 type CurveExt = Ed25519;
667
668 fn is_on_curve(&self) -> Choice {
669 let x2 = self.x.square();
670 let y2 = self.y.square();
671
672 (y2 - x2).ct_eq(&(Fq::one() + ED25519_D * x2 * y2))
673 }
674
675 fn coordinates(&self) -> CtOption<Coordinates<Self>> {
676 Coordinates::from_xy(self.x, self.y)
677 }
678
679 fn from_xy(x: Self::Base, y: Self::Base) -> CtOption<Self> {
680 let p = Ed25519Affine { x, y };
681 CtOption::new(p, p.is_on_curve())
682 }
683
684 fn a() -> Self::Base {
685 unimplemented!()
686 }
687
688 fn b() -> Self::Base {
689 unimplemented!()
690 }
691}
692
693impl_binops_additive!(Ed25519, Ed25519);
694impl_binops_additive!(Ed25519, Ed25519Affine);
695impl_binops_additive_specify_output!(Ed25519Affine, Ed25519Affine, Ed25519);
696impl_binops_additive_specify_output!(Ed25519Affine, Ed25519, Ed25519);
697impl_binops_multiplicative!(Ed25519, Fr);
698impl_binops_multiplicative_mixed!(Ed25519Affine, Fr, Ed25519);
699
700impl<'a> Neg for &'a Ed25519 {
701 type Output = Ed25519;
702
703 fn neg(self) -> Ed25519 {
704 Ed25519 {
705 x: -self.x,
706 y: self.y,
707 z: self.z,
708 t: -self.t,
709 }
710 }
711}
712
713impl Neg for Ed25519 {
714 type Output = Ed25519;
715
716 fn neg(self) -> Ed25519 {
717 -&self
718 }
719}
720
721impl<T> Sum<T> for Ed25519
722where
723 T: core::borrow::Borrow<Ed25519>,
724{
725 fn sum<I>(iter: I) -> Self
726 where
727 I: Iterator<Item = T>,
728 {
729 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
730 }
731}
732
733impl<'a, 'b> Add<&'a Ed25519> for &'b Ed25519 {
734 type Output = Ed25519;
735
736 fn add(self, rhs: &'a Ed25519) -> Ed25519 {
737 let a = (self.x - self.y) * (rhs.x - rhs.y);
755 let b = (self.x + self.y) * (rhs.x + rhs.y);
756 let c = (self.t * rhs.t * ED25519_D).double();
757 let d = (self.z * rhs.z).double();
758
759 let e = b - a;
760 let f = d - c;
761 let g = d + c;
762 let h = b + a;
763
764 Ed25519 {
765 x: e * f,
766 y: g * h,
767 z: f * g,
768 t: e * h,
769 }
770 }
771}
772
773impl<'a, 'b> Add<&'a Ed25519Affine> for &'b Ed25519 {
774 type Output = Ed25519;
775
776 fn add(self, rhs: &'a Ed25519Affine) -> Ed25519 {
777 self + rhs.to_extended()
778 }
779}
780
781impl<'a, 'b> Sub<&'a Ed25519> for &'b Ed25519 {
782 type Output = Ed25519;
783
784 fn sub(self, other: &'a Ed25519) -> Ed25519 {
785 self + (-other)
786 }
787}
788
789impl<'a, 'b> Sub<&'a Ed25519Affine> for &'b Ed25519 {
790 type Output = Ed25519;
791
792 fn sub(self, other: &'a Ed25519Affine) -> Ed25519 {
793 self + (-other)
794 }
795}
796
797#[allow(clippy::suspicious_arithmetic_impl)]
798impl<'a, 'b> Mul<&'b Fr> for &'a Ed25519 {
799 type Output = Ed25519;
800
801 fn mul(self, other: &'b Fr) -> Self::Output {
808 let mut acc = Ed25519::identity();
809 for bit in other
810 .to_repr()
811 .iter()
812 .rev()
813 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
814 .skip(3)
815 {
816 acc = acc.double();
817 acc = Ed25519::conditional_select(&acc, &(acc + self), bit);
818 }
819
820 acc
821 }
822}
823
824impl<'a> Neg for &'a Ed25519Affine {
825 type Output = Ed25519Affine;
826
827 fn neg(self) -> Ed25519Affine {
828 Ed25519Affine {
829 x: -self.x,
830 y: self.y,
831 }
832 }
833}
834
835impl Neg for Ed25519Affine {
836 type Output = Ed25519Affine;
837
838 fn neg(self) -> Ed25519Affine {
839 -&self
840 }
841}
842
843impl<'a, 'b> Add<&'a Ed25519> for &'b Ed25519Affine {
844 type Output = Ed25519;
845
846 fn add(self, rhs: &'a Ed25519) -> Ed25519 {
847 rhs + self
848 }
849}
850
851impl<'a, 'b> Add<&'a Ed25519Affine> for &'b Ed25519Affine {
852 type Output = Ed25519;
853
854 fn add(self, rhs: &'a Ed25519Affine) -> Ed25519 {
855 self.to_extended() + rhs.to_extended()
856 }
857}
858
859impl<'a, 'b> Sub<&'a Ed25519Affine> for &'b Ed25519Affine {
860 type Output = Ed25519;
861
862 fn sub(self, other: &'a Ed25519Affine) -> Ed25519 {
863 self + (-other)
864 }
865}
866
867impl<'a, 'b> Sub<&'a Ed25519> for &'b Ed25519Affine {
868 type Output = Ed25519;
869
870 fn sub(self, other: &'a Ed25519) -> Ed25519 {
871 self + (-other)
872 }
873}
874
875#[allow(clippy::suspicious_arithmetic_impl)]
876impl<'a, 'b> Mul<&'b Fr> for &'a Ed25519Affine {
877 type Output = Ed25519;
878
879 fn mul(self, other: &'b Fr) -> Self::Output {
880 let mut acc = Ed25519::identity();
881
882 for bit in other
889 .to_repr()
890 .iter()
891 .rev()
892 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
893 {
894 acc = acc.double();
895 acc = Ed25519::conditional_select(&acc, &(acc + self), bit);
896 }
897
898 acc
899 }
900}
901
902impl CurveAffineExt for Ed25519Affine {
903 fn into_coordinates(self) -> (Self::Base, Self::Base) {
904 (self.x, self.y)
905 }
906}
907
908pub trait TwistedEdwardsCurveExt: CurveExt {
909 fn a() -> <Self as CurveExt>::Base;
910 fn d() -> <Self as CurveExt>::Base;
911}
912
913impl TwistedEdwardsCurveExt for Ed25519 {
914 fn a() -> Fq {
915 -Fq::ONE
916 }
917
918 fn d() -> Fq {
919 ED25519_D
920 }
921}
922
923pub trait TwistedEdwardsCurveAffineExt: CurveAffineExt {
924 fn a() -> <Self as CurveAffine>::Base;
925 fn d() -> <Self as CurveAffine>::Base;
926}
927
928impl TwistedEdwardsCurveAffineExt for Ed25519Affine {
929 fn a() -> Fq {
930 -Fq::ONE
931 }
932
933 fn d() -> Fq {
934 ED25519_D
935 }
936}
937
938#[test]
939fn test_is_on_curve() {
940 assert!(bool::from(Ed25519Affine::identity().is_on_curve()));
941}
942
943#[test]
944fn test_d_is_non_quadratic_residue() {
945 assert!(bool::from(ED25519_D.sqrt().is_none()));
946 assert!(bool::from((-ED25519_D).sqrt().is_none()));
947 assert!(bool::from((-ED25519_D).invert().unwrap().sqrt().is_none()));
948}
949
950#[test]
951fn test_double() {
952 let p = Ed25519::generator();
953
954 assert_eq!(p.double(), p + p);
955}
956
957#[test]
958fn test_assoc() {
959 let p = Ed25519::from(Ed25519Affine {
960 x: Fq::from_raw([
961 0x4eb5_31fa_487c_0f3e,
962 0x1313_5118_1c90_b35e,
963 0xdb9a_afaf_f32a_26f7,
964 0x5e0c_b226_a2aa_bab4,
965 ]),
966 y: Fq::from_raw([
967 0xbf09_6275_684b_b8c9,
968 0xc7ba_2458_90af_256d,
969 0x5911_9f3e_8638_0eb0,
970 0x3793_de18_2f9f_b1d2,
971 ]),
972 })
973 .mul_by_cofactor();
974 assert!(bool::from(p.is_on_curve()));
975
976 assert_eq!(
977 (p * Fr::from(1000u64)) * Fr::from(3938u64),
978 p * (Fr::from(1000u64) * Fr::from(3938u64)),
979 );
980}
981
982#[test]
983fn test_curve() {
984 crate::tests::curve::curve_tests::<Ed25519>();
985}
986
987#[test]
988fn test_serialization() {
989 crate::tests::curve::random_serialization_test::<Ed25519>();
990}
991
992