Skip to main content

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::FromUniformBytes for Scalar {
224    /// 48 bytes
225    ///
226    /// `L = ceil((ceil(log2(q)) + k) / 8) = ceil((256 + 128) / 8) = 48` bytes are enough to
227    /// guarantee the uniform distribution
228    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        // Having crypto rng for scalar generation is not a hard requirement,
240        // as in some cases it isn't needed. However, `curve25519` lib asks for
241        // it, so we'll trick it
242        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}