ed448_goldilocks/decaf/
affine.rs1use crate::decaf::points::DecafPointRepr;
2use crate::{
3 Decaf448FieldBytes, DecafPoint, DecafScalar, ORDER,
4 curve::twedwards::affine::AffinePoint as InnerAffinePoint, field::FieldElement,
5};
6use elliptic_curve::{
7 CurveGroup, Error, Generate, ctutils,
8 group::{CurveAffine, GroupEncoding},
9 ops::{Mul, MulVartime, Neg},
10 point::{AffineCoordinates, NonIdentity},
11 zeroize::DefaultIsZeroes,
12};
13use rand_core::TryCryptoRng;
14use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
15
16#[derive(Copy, Clone, Debug, Default)]
18pub struct AffinePoint(pub(crate) InnerAffinePoint);
19
20impl AffinePoint {
21 pub const IDENTITY: Self = Self(InnerAffinePoint::IDENTITY);
23
24 pub fn to_decaf(&self) -> DecafPoint {
26 DecafPoint(self.0.to_extended())
27 }
28
29 pub fn x(&self) -> [u8; 56] {
31 self.0.x.to_bytes()
32 }
33
34 pub fn y(&self) -> [u8; 56] {
36 self.0.y.to_bytes()
37 }
38}
39
40impl ConstantTimeEq for AffinePoint {
41 fn ct_eq(&self, other: &Self) -> Choice {
42 self.0.x.ct_eq(&other.0.x) & self.0.y.ct_eq(&other.0.y)
43 }
44}
45
46impl ConditionallySelectable for AffinePoint {
47 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
48 Self(InnerAffinePoint {
49 x: FieldElement::conditional_select(&a.0.x, &b.0.x, choice),
50 y: FieldElement::conditional_select(&a.0.y, &b.0.y, choice),
51 })
52 }
53}
54
55impl ctutils::CtEq for AffinePoint {
56 fn ct_eq(&self, other: &Self) -> ctutils::Choice {
57 ConstantTimeEq::ct_eq(self, other).into()
58 }
59}
60
61impl ctutils::CtSelect for AffinePoint {
62 fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
63 ConditionallySelectable::conditional_select(self, other, choice.into())
64 }
65}
66
67impl PartialEq for AffinePoint {
68 fn eq(&self, other: &Self) -> bool {
69 self.ct_eq(other).into()
70 }
71}
72
73impl Eq for AffinePoint {}
74
75impl AffineCoordinates for AffinePoint {
76 type FieldRepr = Decaf448FieldBytes;
77
78 fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
79 let point = Self(InnerAffinePoint {
80 x: FieldElement::from_bytes(&x.0),
81 y: FieldElement::from_bytes(&y.0),
82 });
83
84 CtOption::new(
85 point,
86 point.0.is_on_curve() & (point * DecafScalar::new(*ORDER)).ct_eq(&DecafPoint::IDENTITY),
87 )
88 }
89
90 fn x(&self) -> Self::FieldRepr {
91 Decaf448FieldBytes::from(self.x())
92 }
93
94 fn y(&self) -> Self::FieldRepr {
95 Decaf448FieldBytes::from(self.y())
96 }
97
98 fn x_is_odd(&self) -> Choice {
99 self.0.x.is_negative()
100 }
101
102 fn y_is_odd(&self) -> Choice {
103 self.0.y.is_negative()
104 }
105}
106
107impl CurveAffine for AffinePoint {
108 type Curve = DecafPoint;
109 type Scalar = DecafScalar;
110
111 fn identity() -> AffinePoint {
112 Self::IDENTITY
113 }
114
115 fn generator() -> AffinePoint {
116 DecafPoint::GENERATOR.to_affine()
117 }
118
119 fn is_identity(&self) -> Choice {
120 self.to_decaf().is_identity()
121 }
122
123 fn to_curve(&self) -> DecafPoint {
124 self.to_decaf()
125 }
126}
127
128impl DefaultIsZeroes for AffinePoint {}
129
130impl Generate for AffinePoint {
131 fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
132 DecafPoint::try_generate_from_rng(rng).map(Into::into)
133 }
134}
135
136impl GroupEncoding for AffinePoint {
137 type Repr = DecafPointRepr;
138
139 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
140 DecafPoint::from_bytes(bytes).map(|point| point.to_affine())
141 }
142
143 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
144 Self::from_bytes(bytes)
146 }
147
148 fn to_bytes(&self) -> Self::Repr {
149 self.to_decaf().to_bytes()
150 }
151}
152
153impl TryFrom<AffinePoint> for NonIdentity<AffinePoint> {
155 type Error = Error;
156
157 fn try_from(affine_point: AffinePoint) -> Result<Self, Error> {
158 NonIdentity::new(affine_point).into_option().ok_or(Error)
159 }
160}
161
162impl From<NonIdentity<AffinePoint>> for AffinePoint {
163 fn from(affine: NonIdentity<AffinePoint>) -> Self {
164 affine.to_point()
165 }
166}
167
168impl Mul<&DecafScalar> for &AffinePoint {
169 type Output = DecafPoint;
170
171 #[inline]
172 fn mul(self, scalar: &DecafScalar) -> DecafPoint {
173 self.to_decaf() * scalar
174 }
175}
176
177impl MulVartime<DecafScalar> for AffinePoint {
178 #[inline]
179 fn mul_vartime(self, scalar: DecafScalar) -> DecafPoint {
180 self.mul_vartime(&scalar)
181 }
182}
183
184impl MulVartime<&DecafScalar> for AffinePoint {
185 #[inline]
186 fn mul_vartime(self, scalar: &DecafScalar) -> DecafPoint {
187 self.to_decaf() * scalar
189 }
190}
191
192impl MulVartime<&DecafScalar> for &AffinePoint {
193 #[inline]
194 fn mul_vartime(self, scalar: &DecafScalar) -> DecafPoint {
195 (*self).mul_vartime(scalar)
196 }
197}
198
199define_mul_variants!(LHS = AffinePoint, RHS = DecafScalar, Output = DecafPoint);
200
201impl Neg for AffinePoint {
202 type Output = AffinePoint;
203
204 fn neg(self) -> Self::Output {
205 self.to_decaf().neg().to_affine()
206 }
207}