ed448_goldilocks/curve/twedwards/
affine.rs1#![allow(dead_code)]
2use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
3use crate::field::FieldElement;
4use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
5
6#[derive(Copy, Clone, Debug, PartialEq, Eq)]
15pub struct AffinePoint {
16 pub(crate) x: FieldElement,
17 pub(crate) y: FieldElement,
18}
19
20impl Default for AffinePoint {
21 fn default() -> AffinePoint {
22 AffinePoint::IDENTITY
23 }
24}
25
26impl AffinePoint {
27 pub(crate) const IDENTITY: AffinePoint = AffinePoint {
29 x: FieldElement::ZERO,
30 y: FieldElement::ONE,
31 };
32
33 pub(crate) fn is_on_curve(&self) -> Choice {
35 let xx = self.x.square();
36 let yy = self.y.square();
37
38 (yy - xx).ct_eq(&(FieldElement::ONE + (FieldElement::TWISTED_D * xx * yy)))
39 }
40
41 pub(crate) fn negate(&self) -> AffinePoint {
43 AffinePoint {
44 x: -self.x,
45 y: self.y,
46 }
47 }
48
49 pub(crate) fn add(&self, other: &AffinePoint) -> AffinePoint {
51 let y_numerator = self.y * other.y + self.x * other.x;
52 let y_denominator =
53 FieldElement::ONE - FieldElement::TWISTED_D * self.x * other.x * self.y * other.y;
54
55 let x_numerator = self.x * other.y + self.y * other.x;
56 let x_denominator =
57 FieldElement::ONE + FieldElement::TWISTED_D * self.x * other.x * self.y * other.y;
58
59 let x = x_numerator * x_denominator.invert();
60 let y = y_numerator * y_denominator.invert();
61 AffinePoint { x, y }
62 }
63
64 pub(crate) fn to_extensible(self) -> ExtensiblePoint {
66 ExtensiblePoint {
67 X: self.x,
68 Y: self.y,
69 Z: FieldElement::ONE,
70 T1: self.x,
71 T2: self.y,
72 }
73 }
74
75 pub(crate) fn to_extended(self) -> ExtendedPoint {
85 self.to_extensible().to_extended()
86 }
87}
88
89#[derive(Copy, Clone)]
92pub struct AffineNielsPoint {
93 pub(crate) y_plus_x: FieldElement,
94 pub(crate) y_minus_x: FieldElement,
95 pub(crate) td: FieldElement,
96}
97
98impl ConditionallySelectable for AffineNielsPoint {
99 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
100 AffineNielsPoint {
101 y_plus_x: FieldElement::conditional_select(&a.y_plus_x, &b.y_plus_x, choice),
102 y_minus_x: FieldElement::conditional_select(&a.y_minus_x, &b.y_minus_x, choice),
103 td: FieldElement::conditional_select(&a.td, &b.td, choice),
104 }
105 }
106}
107
108impl AffineNielsPoint {
109 pub(crate) const IDENTITY: AffineNielsPoint = AffineNielsPoint {
111 y_plus_x: FieldElement::ONE,
112 y_minus_x: FieldElement::ONE,
113 td: FieldElement::ZERO,
114 };
115
116 pub(crate) fn equals(&self, other: &AffineNielsPoint) -> bool {
119 (self.y_minus_x == other.y_minus_x)
120 && (self.y_plus_x == other.y_plus_x)
121 && (self.td == other.td)
122 }
123
124 pub(crate) fn to_extensible(self) -> ExtensiblePoint {
126 ExtensiblePoint {
127 X: self.y_plus_x - self.y_minus_x,
128 Y: self.y_minus_x + self.y_plus_x,
129 Z: FieldElement::ONE,
130 T1: self.y_plus_x,
131 T2: self.y_minus_x,
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138
139 use super::*;
140
141 #[test]
142 fn test_negation() {
143 use crate::TWISTED_EDWARDS_BASE_POINT;
144 let a = TWISTED_EDWARDS_BASE_POINT.to_extensible().to_affine();
145 assert_eq!(a.is_on_curve().unwrap_u8(), 1);
146
147 let neg_a = a.negate();
148 let got = neg_a.add(&a);
149 assert!(got == AffinePoint::IDENTITY);
150 }
151}