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::Samplable for Scalar {
224 fn random<R: rand_core::RngCore>(rng: &mut R) -> Self {
225 struct FakeCryptoRng<R>(R);
229 impl<R: rand_core::RngCore> rand_core::RngCore for FakeCryptoRng<R> {
230 fn next_u32(&mut self) -> u32 {
231 self.0.next_u32()
232 }
233 fn next_u64(&mut self) -> u64 {
234 self.0.next_u64()
235 }
236 fn fill_bytes(&mut self, dest: &mut [u8]) {
237 self.0.fill_bytes(dest)
238 }
239 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
240 self.0.try_fill_bytes(dest)
241 }
242 }
243 impl<R> rand_core::CryptoRng for FakeCryptoRng<R> {}
244
245 Self(curve25519::Scalar::random(&mut FakeCryptoRng(rng)))
246 }
247}
248
249impl subtle::ConstantTimeEq for Scalar {
250 fn ct_eq(&self, other: &Self) -> subtle::Choice {
251 self.0.ct_eq(&other.0)
252 }
253}
254
255impl subtle::ConditionallySelectable for Scalar {
256 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
257 Self(subtle::ConditionallySelectable::conditional_select(
258 &a.0, &b.0, choice,
259 ))
260 }
261}
262
263impl generic_ec_core::IntegerEncoding for Scalar {
264 type Bytes = [u8; 32];
265
266 fn to_be_bytes(&self) -> Self::Bytes {
267 let mut bytes = self.to_le_bytes();
268 bytes.reverse();
269 bytes
270 }
271
272 fn to_le_bytes(&self) -> Self::Bytes {
273 self.0.to_bytes()
274 }
275
276 fn from_be_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
277 let mut bytes = *bytes;
278 bytes.reverse();
279 Self::from_le_bytes_exact(&bytes)
280 }
281
282 fn from_le_bytes_exact(bytes: &Self::Bytes) -> Option<Self> {
283 Option::from(curve25519::Scalar::from_canonical_bytes(*bytes)).map(Self)
284 }
285
286 fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
287 crate::utils::scalar_from_be_bytes_mod_order_reducing_32_64(bytes, &Self::ONE)
288 }
289
290 fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
291 crate::utils::scalar_from_le_bytes_mod_order_reducing_32_64(bytes, &Self::ONE)
292 }
293}
294
295impl core::cmp::PartialOrd for Scalar {
296 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
297 Some(self.cmp(other))
298 }
299}
300
301impl core::cmp::Ord for Scalar {
302 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
303 self.0.as_bytes().cmp(other.0.as_bytes())
304 }
305}
306
307impl generic_ec_core::Reduce<32> for Scalar {
308 fn from_be_array_mod_order(bytes: &[u8; 32]) -> Self {
309 let mut bytes = *bytes;
310 bytes.reverse();
311 Self(curve25519::Scalar::from_bytes_mod_order(bytes))
312 }
313 fn from_le_array_mod_order(bytes: &[u8; 32]) -> Self {
314 Self(curve25519::Scalar::from_bytes_mod_order(*bytes))
315 }
316}
317impl generic_ec_core::Reduce<64> for Scalar {
318 fn from_be_array_mod_order(bytes: &[u8; 64]) -> Self {
319 let mut bytes = *bytes;
320 bytes.reverse();
321 Self(curve25519::Scalar::from_bytes_mod_order_wide(&bytes))
322 }
323 fn from_le_array_mod_order(bytes: &[u8; 64]) -> Self {
324 Self(curve25519::Scalar::from_bytes_mod_order_wide(bytes))
325 }
326}