generic_ec_curves/
ed25519.rs

1//! Ed25519 curve
2
3/// Ed25519 curve
4#[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    // We don't expose affine coordinates for ed25519 curve
21    type CoordinateArray = [u8; 0];
22}
23
24/// Ed25519 point
25#[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/// Ed25519 scalar
143#[derive(Default, Clone, Copy, PartialEq, Eq, zeroize::Zeroize)]
144pub struct Scalar(pub curve25519::Scalar);
145
146impl Scalar {
147    /// Scalar equal to 1
148    pub const ONE: Self = Self(curve25519::Scalar::ONE);
149    /// Scalar equal to 0
150    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        // Having crypto rng for scalar generation is not a hard requirement,
226        // as in some cases it isn't needed. However, `curve25519` lib asks for
227        // it, so we'll trick it
228        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}