1use super::curve::{Arithmetic, Curve, CurveError, choose_root};
4use super::field::{Base, Field, invert_all, reduced, sqrt_ratio, with_prime};
5use super::group::{Coordinates, Group};
6use super::montgomery::Montgomery;
7use super::point::Point;
8use crate::math::numbers::{ByteOrder, Number};
9
10pub struct Edwards {
30 base: Base,
32 a: Number,
34 d: Number,
36 a_limbs: Vec<u64>,
38 d_limbs: Vec<u64>,
40 minus_one: bool,
42}
43
44impl Edwards {
45 pub fn new(a: &Number, d: &Number, p: &Number) -> Result<Edwards, CurveError> {
54 let three = Number::new_from_u8(3, p.byte_order);
55 if p.is_negative() || *p <= three || !p.is_probable_prime() {
56 return Err(CurveError::NotPrime);
57 }
58 let a = reduced(a, p);
59 let d = reduced(d, p);
60 if a.is_zero() || d.is_zero() || a == d {
61 return Err(CurveError::Singular);
62 }
63 if a.jacobi(p) != 1 || d.jacobi(p) != -1 {
64 return Err(CurveError::NotComplete);
65 }
66 let base = Base::new(p);
67 let n = with_prime!(&base.prime, f => f.limbs());
68 let (mut a_limbs, mut d_limbs) = (vec![0; n], vec![0; n]);
69 with_prime!(&base.prime, f => {
70 f.store(&f.enter(&a), &mut a_limbs);
71 f.store(&f.enter(&d), &mut d_limbs);
72 });
73 let minus_one = &a + 1u8 == *p;
74 Ok(Edwards {
75 base,
76 a,
77 d,
78 a_limbs,
79 d_limbs,
80 minus_one,
81 })
82 }
83
84 pub fn a(&self) -> &Number {
86 &self.a
87 }
88
89 pub fn d(&self) -> &Number {
91 &self.d
92 }
93
94 pub fn to_montgomery(&self) -> Montgomery {
97 let (ma, mb) = self.montgomery_coefficients();
98 Montgomery::new(&ma, &mb, &self.base.p).unwrap_or_else(|_| unreachable!())
100 }
101
102 pub fn map_to_montgomery<'t>(
111 &self,
112 target: &'t Montgomery,
113 point: &Point<'_, Edwards>,
114 ) -> Point<'t, Montgomery> {
115 point.check_curve(self);
116 let p = &self.base.p;
117 let (ma, mb) = self.montgomery_coefficients();
118 assert!(
119 target.modulus() == p && (target.a(), target.b()) == (&ma, &mb),
120 "the target is not this curve's Montgomery form"
121 );
122 let Some((x, y)) = point.coordinates() else {
123 return target.identity();
124 };
125 if x.is_zero() {
126 if y == Number::new_from_u8(1, p.byte_order) {
127 return target.identity();
128 }
129 let zero = Number::new_from_u8(0, p.byte_order);
130 return target
131 .point(&zero, &zero)
132 .unwrap_or_else(|_| unreachable!());
133 }
134 let inv = (1u8 - &y).rem_euclid(p).mod_inverse(p).unwrap_or_default();
135 let u = ((&y + 1u8) * inv).rem_euclid(p);
136 let v = (&u * x.mod_inverse(p).unwrap_or_default()).rem_euclid(p);
137 target.point(&u, &v).unwrap_or_else(|_| unreachable!())
139 }
140
141 fn montgomery_coefficients(&self) -> (Number, Number) {
143 let (a, d, p) = (&self.a, &self.d, &self.base.p);
144 let i = (a - d).rem_euclid(p).mod_inverse(p).unwrap_or_default();
145 let ma = ((a + d) * 2u8 * &i).rem_euclid(p);
146 let mb = (&i * 4u8).rem_euclid(p);
147 (ma, mb)
148 }
149
150 fn encoded_len(&self) -> usize {
152 self.base.p.bits() as usize / 8 + 1
153 }
154}
155
156#[derive(Clone)]
158pub(super) struct Extended<E> {
159 x: E,
160 y: E,
161 z: E,
162 t: E,
163}
164
165#[derive(Clone)]
168pub(super) struct Cached<E> {
169 u: E,
170 v: E,
171 z: Option<E>,
172 t: E,
173}
174
175struct Doubled<E> {
177 x: E,
178 y: E,
179 z: E,
180 e: E,
181 h: E,
182}
183
184pub(super) struct Edw<'a, F: Field> {
186 f: &'a F,
187 a: F::E,
188 d: F::E,
189 minus_one: bool,
190}
191
192macro_rules! with_group {
194 ($c:expr, $g:ident => $body:expr) => {
195 with_prime!(&$c.base.prime, f => {
196 let $g = Edw {
197 f,
198 a: f.load(&$c.a_limbs),
199 d: f.load(&$c.d_limbs),
200 minus_one: $c.minus_one,
201 };
202 $body
203 })
204 };
205}
206
207impl<F: Field> Edw<'_, F> {
208 #[inline]
211 fn double_parts(&self, x: &F::E, y: &F::E, z: &F::E) -> Doubled<F::E> {
212 let f = self.f;
213 let a = f.sqr(x);
214 let b = f.sqr(y);
215 let c = f.twice(&f.sqr(z));
216 let d = if self.minus_one {
217 f.neg(&a)
218 } else {
219 f.mul(&self.a, &a)
220 };
221 let e = f.sub(&f.sub(&f.sqr(&f.add(x, y)), &a), &b);
222 let g = f.add(&d, &b);
223 let ff = f.sub(&g, &c);
224 let h = f.sub(&d, &b);
225 Doubled {
226 x: f.mul(&e, &ff),
227 y: f.mul(&g, &h),
228 z: f.mul(&ff, &g),
229 e,
230 h,
231 }
232 }
233
234 #[inline(always)]
236 fn combine(&self, e: &F::E, ff: &F::E, g: &F::E, h: &F::E) -> Extended<F::E> {
237 let f = self.f;
238 Extended {
239 x: f.mul(e, ff),
240 y: f.mul(g, h),
241 z: f.mul(ff, g),
242 t: f.mul(e, h),
243 }
244 }
245}
246
247impl<F: Field> Group for Edw<'_, F> {
248 type F = F;
249 type Proj = Extended<F::E>;
250 type Cached = Cached<F::E>;
251 const CACHED: usize = 3;
253
254 #[inline(always)]
255 fn field(&self) -> &F {
256 self.f
257 }
258
259 fn identity(&self) -> Extended<F::E> {
260 let f = self.f;
261 Extended {
262 x: f.zero(),
263 y: f.one(),
264 z: f.one(),
265 t: f.zero(),
266 }
267 }
268
269 fn is_identity(&self, p: &Extended<F::E>) -> bool {
270 let f = self.f;
271 f.is_zero(&p.x) && f.equal(&p.y, &p.z)
272 }
273
274 fn load(&self, x: &[u64]) -> Extended<F::E> {
275 let (f, n) = (self.f, self.f.limbs());
276 Extended {
277 x: f.load(&x[..n]),
278 y: f.load(&x[n..2 * n]),
279 z: f.load(&x[2 * n..3 * n]),
280 t: f.load(&x[3 * n..4 * n]),
281 }
282 }
283
284 fn store(&self, p: &Extended<F::E>, r: &mut [u64]) {
285 let (f, n) = (self.f, self.f.limbs());
286 f.store(&p.x, &mut r[..n]);
287 f.store(&p.y, &mut r[n..2 * n]);
288 f.store(&p.z, &mut r[2 * n..3 * n]);
289 f.store(&p.t, &mut r[3 * n..4 * n]);
290 }
291
292 fn neg(&self, p: &Extended<F::E>) -> Extended<F::E> {
293 let f = self.f;
294 Extended {
295 x: f.neg(&p.x),
296 y: p.y.clone(),
297 z: p.z.clone(),
298 t: f.neg(&p.t),
299 }
300 }
301
302 fn double(&self, p: &Extended<F::E>) -> Extended<F::E> {
303 let d = self.double_parts(&p.x, &p.y, &p.z);
304 Extended {
305 t: self.f.mul(&d.e, &d.h),
306 x: d.x,
307 y: d.y,
308 z: d.z,
309 }
310 }
311
312 fn double_n(&self, p: &mut Extended<F::E>, n: usize) {
313 if n == 0 {
314 return;
315 }
316 let (mut x, mut y, mut z) = (p.x.clone(), p.y.clone(), p.z.clone());
317 for _ in 1..n {
318 let d = self.double_parts(&x, &y, &z);
319 (x, y, z) = (d.x, d.y, d.z);
320 }
321 let d = self.double_parts(&x, &y, &z);
322 *p = Extended {
323 t: self.f.mul(&d.e, &d.h),
324 x: d.x,
325 y: d.y,
326 z: d.z,
327 };
328 }
329
330 fn add(&self, p: &Extended<F::E>, q: &Extended<F::E>) -> Extended<F::E> {
331 self.add_cached(p, &self.cache_one(q))
332 }
333
334 fn equal(&self, p: &Extended<F::E>, q: &Extended<F::E>) -> bool {
335 let f = self.f;
336 f.equal(&f.mul(&p.x, &q.z), &f.mul(&q.x, &p.z))
337 && f.equal(&f.mul(&p.y, &q.z), &f.mul(&q.y, &p.z))
338 }
339
340 fn cache(&self, p: &[Extended<F::E>]) -> Vec<Cached<F::E>> {
341 p.iter().map(|q| self.cache_one(q)).collect()
342 }
343
344 fn cache_affine(&self, p: &[Extended<F::E>]) -> Vec<Cached<F::E>> {
346 let f = self.f;
347 let mut z: Vec<F::E> = p.iter().map(|q| q.z.clone()).collect();
348 invert_all(f, &mut z);
349 p.iter()
350 .zip(z.iter())
351 .map(|(q, i)| {
352 let (x, y) = (f.mul(&q.x, i), f.mul(&q.y, i));
353 let t = f.mul(&f.mul(&x, &y), &self.d);
354 if self.minus_one {
355 Cached {
356 u: f.add(&y, &x),
357 v: f.sub(&y, &x),
358 z: None,
359 t: f.twice(&t),
360 }
361 } else {
362 Cached {
363 u: x,
364 v: y,
365 z: None,
366 t,
367 }
368 }
369 })
370 .collect()
371 }
372
373 fn add_cached(&self, p: &Extended<F::E>, c: &Cached<F::E>) -> Extended<F::E> {
376 let f = self.f;
377 if self.minus_one {
378 let a = f.mul(&f.sub(&p.y, &p.x), &c.v);
379 let b = f.mul(&f.add(&p.y, &p.x), &c.u);
380 let cc = f.mul(&p.t, &c.t);
381 let d = match &c.z {
382 Some(z) => f.mul(&p.z, z),
383 None => f.twice(&p.z),
384 };
385 self.combine(
386 &f.sub(&b, &a),
387 &f.sub(&d, &cc),
388 &f.add(&d, &cc),
389 &f.add(&b, &a),
390 )
391 } else {
392 let a = f.mul(&p.x, &c.u);
393 let b = f.mul(&p.y, &c.v);
394 let cc = f.mul(&p.t, &c.t);
395 let d = match &c.z {
396 Some(z) => f.mul(&p.z, z),
397 None => p.z.clone(),
398 };
399 let e = f.sub(
400 &f.sub(&f.mul(&f.add(&p.x, &p.y), &f.add(&c.u, &c.v)), &a),
401 &b,
402 );
403 self.combine(
404 &e,
405 &f.sub(&d, &cc),
406 &f.add(&d, &cc),
407 &f.sub(&b, &f.mul(&self.a, &a)),
408 )
409 }
410 }
411
412 fn neg_cached(&self, c: &Cached<F::E>) -> Cached<F::E> {
413 let f = self.f;
414 if self.minus_one {
415 Cached {
416 u: c.v.clone(),
417 v: c.u.clone(),
418 z: c.z.clone(),
419 t: f.neg(&c.t),
420 }
421 } else {
422 Cached {
423 u: f.neg(&c.u),
424 v: c.v.clone(),
425 z: c.z.clone(),
426 t: f.neg(&c.t),
427 }
428 }
429 }
430
431 fn store_cached(&self, c: &Cached<F::E>, r: &mut [u64]) {
433 let (f, n) = (self.f, self.f.limbs());
434 f.store(&c.u, &mut r[..n]);
435 f.store(&c.v, &mut r[n..2 * n]);
436 f.store(&c.t, &mut r[2 * n..3 * n]);
437 }
438
439 fn load_cached(&self, x: &[u64]) -> Cached<F::E> {
440 let (f, n) = (self.f, self.f.limbs());
441 Cached {
442 u: f.load(&x[..n]),
443 v: f.load(&x[n..2 * n]),
444 z: None,
445 t: f.load(&x[2 * n..3 * n]),
446 }
447 }
448
449 fn of_affine(&self, x: &F::E, y: &F::E) -> Extended<F::E> {
450 let f = self.f;
451 Extended {
452 x: x.clone(),
453 y: y.clone(),
454 z: f.one(),
455 t: f.mul(x, y),
456 }
457 }
458
459 fn affine_all(&self, p: &[Extended<F::E>]) -> Vec<Option<Coordinates<F>>> {
460 let f = self.f;
461 let mut z: Vec<F::E> = p.iter().map(|q| q.z.clone()).collect();
462 invert_all(f, &mut z);
463 p.iter()
464 .zip(z.iter())
465 .map(|(q, i)| Some((f.mul(&q.x, i), f.mul(&q.y, i))))
466 .collect()
467 }
468}
469
470impl<F: Field> Edw<'_, F> {
471 fn cache_one(&self, q: &Extended<F::E>) -> Cached<F::E> {
473 let f = self.f;
474 if self.minus_one {
475 Cached {
476 u: f.add(&q.y, &q.x),
477 v: f.sub(&q.y, &q.x),
478 z: Some(f.twice(&q.z)),
479 t: f.twice(&f.mul(&q.t, &self.d)),
480 }
481 } else {
482 Cached {
483 u: q.x.clone(),
484 v: q.y.clone(),
485 z: Some(q.z.clone()),
486 t: f.mul(&q.t, &self.d),
487 }
488 }
489 }
490
491 fn on_curve(&self, x: &F::E, y: &F::E) -> bool {
493 let f = self.f;
494 let (xx, yy) = (f.sqr(x), f.sqr(y));
495 f.equal(
496 &f.add(&f.mul(&self.a, &xx), &yy),
497 &f.add(&f.one(), &f.mul(&self.d, &f.mul(&xx, &yy))),
498 )
499 }
500
501 fn x_of(&self, y: &F::E, base: &Base) -> Option<F::E> {
504 let f = self.f;
505 let yy = f.sqr(y);
506 let u = f.sub(&yy, &f.one());
507 let v = f.sub(&f.mul(&self.d, &yy), &self.a);
508 sqrt_ratio(f, base.sqrt_plan(), &u, &v)
509 }
510}
511
512impl Arithmetic for Edwards {
513 const COORDINATES: usize = 4;
514
515 fn base(&self) -> &Base {
516 &self.base
517 }
518
519 fn same_curve(&self, other: &Self) -> bool {
520 self.base.p == other.base.p && self.a == other.a && self.d == other.d
521 }
522
523 fn satisfied(&self, x: &Number, y: &Number) -> bool {
524 with_group!(self, g => g.on_curve(&g.f.enter(x), &g.f.enter(y)))
525 }
526
527 fn lift_limbs(&self, y: &Number, odd: bool) -> Option<Vec<u64>> {
528 with_group!(self, g => {
529 let f = g.f;
530 let ey = f.enter(y);
531 let x = choose_root(f, g.x_of(&ey, &self.base)?, odd)?;
532 let mut r = vec![0; 4 * f.limbs()];
533 g.store(&g.of_affine(&x, &ey), &mut r);
534 Some(r)
535 })
536 }
537
538 fn encode(&self, xy: Option<(&Number, &Number)>, compressed: bool) -> Vec<u8> {
539 let len = self.encoded_len();
540 let le = |n: &Number| {
541 let mut b = super::curve::fixed_be(n, len);
542 b.reverse();
543 b
544 };
545 let Some((x, y)) = xy else {
546 return Vec::new();
547 };
548 if compressed {
549 let mut out = le(y);
550 out[len - 1] |= u8::from(x.bit(0)) << 7;
551 out
552 } else {
553 let mut out = le(x);
554 out.extend_from_slice(&le(y));
555 out
556 }
557 }
558
559 fn decode(&self, bytes: &[u8]) -> Option<Vec<u64>> {
560 let len = self.encoded_len();
561 let order = self.base.p.byte_order;
562 let number = |b: &[u8]| {
563 let mut n = Number::new(b.to_vec(), ByteOrder::LittleEndian);
564 if order == ByteOrder::BigEndian {
565 n.value.reverse();
566 n.byte_order = order;
567 }
568 (n < self.base.p).then_some(n)
569 };
570 if bytes.len() == len {
571 let odd = bytes[len - 1] >> 7 != 0;
572 let mut b = bytes.to_vec();
573 b[len - 1] &= 0x7f;
574 self.lift_limbs(&number(&b)?, odd)
575 } else if bytes.len() == 2 * len {
576 let (x, y) = (number(&bytes[..len])?, number(&bytes[len..])?);
577 self.satisfied(&x, &y).then(|| self.affine_limbs(&x, &y))
578 } else {
579 None
580 }
581 }
582
583 super::curve::arithmetic!(with_group);
584}
585
586impl Curve for Edwards {
587 fn discriminant(&self) -> Number {
589 let (a, d, p) = (&self.a, &self.d, &self.base.p);
590 let m = (a - d).rem_euclid(p);
591 let m2 = (&m * &m).rem_euclid(p);
592 let sixteen = Number::new_from_u8(16, p.byte_order);
593 (a * d * &m2 * &m2 * sixteen.mod_inverse(p).unwrap_or_default()).rem_euclid(p)
594 }
595
596 fn j_invariant(&self) -> Number {
598 let (a, d, p) = (&self.a, &self.d, &self.base.p);
599 let t = (a * a + a * d * 14u8 + d * d).rem_euclid(p);
600 let m = (a - d).rem_euclid(p);
601 let m2 = (&m * &m).rem_euclid(p);
602 let den = (a * d * &m2 * &m2).rem_euclid(p);
603 (&t * &t * &t * 16u8 * den.mod_inverse(p).unwrap_or_default()).rem_euclid(p)
604 }
605}