Skip to main content

ed448_goldilocks/curve/twedwards/
affine.rs

1#![allow(dead_code)]
2use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
3use crate::field::FieldElement;
4use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
5
6/// This point representation is not a part of the API.
7///
8/// AffinePoint is mainly used as a convenience struct.
9/// XXX: Initially, I wanted to leave some of these in the library to help
10/// others learn. So if you are scrubbing the commit history. Hopefully they were helpful.
11///
12/// Represents an AffinePoint on the Twisted Edwards Curve
13/// with Equation y^2 - x^2 = 1 - (TWISTED_D) * x^2 * y^2
14#[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    /// Identity element
28    pub(crate) const IDENTITY: AffinePoint = AffinePoint {
29        x: FieldElement::ZERO,
30        y: FieldElement::ONE,
31    };
32
33    /// Checks if the AffinePoint is on the TwistedEdwards curve
34    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    // Negates an AffinePoint
42    pub(crate) fn negate(&self) -> AffinePoint {
43        AffinePoint {
44            x: -self.x,
45            y: self.y,
46        }
47    }
48
49    /// Adds an AffinePoint onto an AffinePoint
50    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    /// Converts an AffinePoint to an ExtensiblePoint
65    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    // /// Converts an AffinePoint to an AffineNielsPoint
76    // pub(crate) fn to_affine_niels(&self) -> AffineNielsPoint {
77    //     AffineNielsPoint {
78    //         y_plus_x: self.y + self.x,
79    //         y_minus_x: self.y - self.x,
80    //         td: self.x * self.y * FieldElement::TWISTED_D,
81    //     }
82    // }
83    /// Converts an An AffinePoint to an ExtendedPoint
84    pub(crate) fn to_extended(self) -> ExtendedPoint {
85        self.to_extensible().to_extended()
86    }
87}
88
89/// Represents a PreComputed or Cached AffinePoint
90///  ((y+x)/2, (y-x)/2, dxy)
91#[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    /// Returns the identity element for an AffineNielsPoint
110    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    /// Checks if two AffineNielsPoints are equal
117    /// Returns true if they are
118    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    /// Converts an AffineNielsPoint to an ExtensiblePoint
125    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}