generic_ec_curves/
ed25519.rs1#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Default, zeroize::Zeroize)]
5pub struct Ed25519 {
6 _private: (),
7}
8
9impl generic_ec_core::Curve for Ed25519 {
10 const CURVE_NAME: &'static str = "ed25519";
11
12 type Point = Point;
13 type Scalar = Scalar;
14
15 type CompressedPointArray = <Point as generic_ec_core::CompressedEncoding>::Bytes;
16 type UncompressedPointArray = <Point as generic_ec_core::UncompressedEncoding>::Bytes;
17
18 type ScalarArray = <Scalar as generic_ec_core::IntegerEncoding>::Bytes;
19
20 type CoordinateArray = [u8; 0];
22}
23
24#[derive(Clone, Copy, PartialEq, Eq, zeroize::Zeroize)]
26#[repr(transparent)]
27pub struct Point(pub curve25519::EdwardsPoint);
28
29impl generic_ec_core::Additive for Point {
30 #[inline]
31 fn add(a: &Self, b: &Self) -> Self {
32 Self(a.0 + b.0)
33 }
34
35 #[inline]
36 fn sub(a: &Self, b: &Self) -> Self {
37 Self(a.0 - b.0)
38 }
39
40 #[inline]
41 fn negate(x: &Self) -> Self {
42 Self(-x.0)
43 }
44}
45
46impl From<generic_ec_core::CurveGenerator> for Point {
47 #[inline]
48 fn from(_: generic_ec_core::CurveGenerator) -> Self {
49 Self(group::Group::generator())
50 }
51}
52
53impl generic_ec_core::Zero for Point {
54 fn zero() -> Self {
55 Self(group::Group::identity())
56 }
57
58 fn is_zero(x: &Self) -> subtle::Choice {
59 subtle::ConstantTimeEq::ct_eq(x, &Self::zero())
60 }
61}
62
63impl generic_ec_core::OnCurve for Point {
64 #[inline]
65 fn is_on_curve(&self) -> subtle::Choice {
66 subtle::Choice::from(1)
67 }
68}
69
70impl generic_ec_core::SmallFactor for Point {
71 #[inline]
72 fn is_torsion_free(&self) -> subtle::Choice {
73 subtle::Choice::from(u8::from(self.0.is_torsion_free()))
74 }
75}
76
77impl subtle::ConstantTimeEq for Point {
78 #[inline]
79 fn ct_eq(&self, other: &Self) -> subtle::Choice {
80 self.0.ct_eq(&other.0)
81 }
82}
83
84impl subtle::ConditionallySelectable for Point {
85 #[inline]
86 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
87 Self(subtle::ConditionallySelectable::conditional_select(
88 &a.0, &b.0, choice,
89 ))
90 }
91}
92
93impl generic_ec_core::CompressedEncoding for Point {
94 type Bytes = [u8; 32];
95
96 fn to_bytes_compressed(&self) -> Self::Bytes {
97 self.0.compress().to_bytes()
98 }
99}
100impl generic_ec_core::UncompressedEncoding for Point {
101 type Bytes = <Self as generic_ec_core::CompressedEncoding>::Bytes;
102
103 fn to_bytes_uncompressed(&self) -> Self::Bytes {
104 <Self as generic_ec_core::CompressedEncoding>::to_bytes_compressed(self)
105 }
106}
107
108impl generic_ec_core::Decode for Point {
109 fn decode(bytes: &[u8]) -> Option<Self> {
110 let compressed = curve25519::edwards::CompressedEdwardsY::from_slice(bytes).ok()?;
111 compressed.decompress().map(Self)
112 }
113}
114
115impl core::cmp::PartialOrd for Point {
116 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
117 Some(self.cmp(other))
118 }
119}
120
121impl core::cmp::Ord for Point {
122 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
123 self.0
124 .compress()
125 .as_bytes()
126 .cmp(other.0.compress().as_bytes())
127 }
128}
129
130impl core::hash::Hash for Point {
131 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
132 self.0.compress().as_bytes().hash(state)
133 }
134}
135
136impl Default for Point {
137 fn default() -> Self {
138 Self(group::Group::identity())
139 }
140}
141
142#[derive(Default, Clone, Copy, PartialEq, Eq, zeroize::Zeroize)]
144pub struct Scalar(pub curve25519::Scalar);
145
146impl Scalar {
147 pub const ONE: Self = Self(curve25519::Scalar::ONE);
149 pub const ZERO: Self = Self(curve25519::Scalar::ZERO);
151}
152
153impl generic_ec_core::Additive for Scalar {
154 #[inline]
155 fn add(a: &Self, b: &Self) -> Self {
156 Self(a.0 + b.0)
157 }
158
159 #[inline]
160 fn sub(a: &Self, b: &Self) -> Self {
161 Self(a.0 - b.0)
162 }
163
164 #[inline]
165 fn negate(x: &Self) -> Self {
166 Self(-x.0)
167 }
168}
169
170impl generic_ec_core::Multiplicative<Scalar> for Scalar {
171 type Output = Scalar;
172
173 #[inline]
174 fn mul(a: &Self, b: &Scalar) -> Self::Output {
175 Self(a.0 * b.0)
176 }
177}
178
179impl generic_ec_core::Multiplicative<Point> for Scalar {
180 type Output = Point;
181 #[inline]
182 fn mul(a: &Self, b: &Point) -> Self::Output {
183 Point(a.0 * b.0)
184 }
185}
186
187impl generic_ec_core::Multiplicative<generic_ec_core::CurveGenerator> for Scalar {
188 type Output = Point;
189
190 #[inline]
191 fn mul(a: &Self, _: &generic_ec_core::CurveGenerator) -> Self::Output {
192 use curve25519::traits::BasepointTable;
193 Point(curve25519::constants::ED25519_BASEPOINT_TABLE.mul_base(&a.0))
194 }
195}
196
197impl generic_ec_core::Invertible for Scalar {
198 fn invert(x: &Self) -> subtle::CtOption<Self> {
199 subtle::CtOption::new(Self(x.0.invert()), !generic_ec_core::Zero::is_zero(x))
200 }
201}
202
203impl generic_ec_core::Zero for Scalar {
204 fn zero() -> Self {
205 Self(curve25519::Scalar::ZERO)
206 }
207
208 fn is_zero(x: &Self) -> subtle::Choice {
209 subtle::ConstantTimeEq::ct_eq(&x.0, &curve25519::Scalar::ZERO)
210 }
211}
212
213impl generic_ec_core::One for Scalar {
214 fn one() -> Self {
215 Self(curve25519::Scalar::ONE)
216 }
217
218 fn is_one(x: &Self) -> subtle::Choice {
219 subtle::ConstantTimeEq::ct_eq(&x.0, &curve25519::Scalar::ONE)
220 }
221}
222
223impl generic_ec_core::FromUniformBytes for Scalar {
224 type Bytes = [u8; 48];
229
230 fn from_uniform_bytes(bytes: &Self::Bytes) -> Self {
231 let mut bytes_le = [0u8; 64];
232 bytes_le[..48].copy_from_slice(bytes);
233 Self(curve25519::Scalar::from_bytes_mod_order_wide(&bytes_le))
234 }
235}
236
237impl generic_ec_core::SamplableVartime for Scalar {
238 fn random_vartime(rng: &mut impl rand_core::RngCore) -> Self {
239 struct FakeCryptoRng<R>(R);
243 impl<R: rand_core::RngCore> rand_core::RngCore for FakeCryptoRng<R> {
244 fn next_u32(&mut self) -> u32 {
245 self.0.next_u32()
246 }
247 fn next_u64(&mut self) -> u64 {
248 self.0.next_u64()
249 }
250 fn fill_bytes(&mut self, dest: &mut [u8]) {
251 self.0.fill_bytes(dest)
252 }
253 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
254 self.0.try_fill_bytes(dest)
255 }
256 }
257 impl<R> rand_core::CryptoRng for FakeCryptoRng<R> {}
258
259 Self(curve25519::Scalar::random(&mut FakeCryptoRng(rng)))
260 }
261}
262
263impl subtle::ConstantTimeEq for Scalar {
264 fn ct_eq(&self, other: &Self) -> subtle::Choice {
265 self.0.ct_eq(&other.0)
266 }
267}
268
269impl subtle::ConditionallySelectable for Scalar {
270 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
271 Self(subtle::ConditionallySelectable::conditional_select(
272 &a.0, &b.0, choice,
273 ))
274 }
275}
276
277impl generic_ec_core::IntegerEncoding for Scalar {
278 type Bytes = [u8; 32];
279
280 fn to_be_bytes(&self) -> Self::Bytes {
281 let mut bytes = self.to_le_bytes();
282 bytes.reverse();
283 bytes
284 }
285
286 fn to_le_bytes(&self) -> Self::Bytes {
287 self.0.to_bytes()
288 }
289
290 fn from_be_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
291 let mut bytes = *bytes;
292 bytes.reverse();
293 Self::from_le_bytes_exact(&bytes)
294 }
295
296 fn from_le_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
297 Option::from(curve25519::Scalar::from_canonical_bytes(*bytes)).map(Self)
298 }
299
300 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
301 crate::utils::scalar_from_be_bytes_mod_order_reducing_32_64(bytes, &Self::ONE)
302 }
303
304 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
305 crate::utils::scalar_from_le_bytes_mod_order_reducing_32_64(bytes, &Self::ONE)
306 }
307}
308
309impl core::cmp::PartialOrd for Scalar {
310 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
311 Some(self.cmp(other))
312 }
313}
314
315impl core::cmp::Ord for Scalar {
316 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
317 self.0.as_bytes().cmp(other.0.as_bytes())
318 }
319}
320
321impl generic_ec_core::Reduce<32> for Scalar {
322 fn from_be_array_mod_order(bytes: &[u8; 32]) -> Self {
323 let mut bytes = *bytes;
324 bytes.reverse();
325 Self(curve25519::Scalar::from_bytes_mod_order(bytes))
326 }
327 fn from_le_array_mod_order(bytes: &[u8; 32]) -> Self {
328 Self(curve25519::Scalar::from_bytes_mod_order(*bytes))
329 }
330}
331impl generic_ec_core::Reduce<64> for Scalar {
332 fn from_be_array_mod_order(bytes: &[u8; 64]) -> Self {
333 let mut bytes = *bytes;
334 bytes.reverse();
335 Self(curve25519::Scalar::from_bytes_mod_order_wide(&bytes))
336 }
337 fn from_le_array_mod_order(bytes: &[u8; 64]) -> Self {
338 Self(curve25519::Scalar::from_bytes_mod_order_wide(bytes))
339 }
340}