generic_ec_core/
lib.rs

1//! This crate contains core traits for [`generic-ec`](https://docs.rs/generic-ec) crate.
2//! You should only need these traits if you implement your own [`Curve`] instance.
3//! Otherwise, `generic-ec` API should suffice.
4
5#![no_std]
6#![cfg_attr(not(test), forbid(unused_crate_dependencies))]
7#![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::expect_used))]
8#![forbid(missing_docs)]
9
10use core::fmt::Debug;
11use core::hash::Hash;
12
13use generic_array::{ArrayLength, GenericArray};
14use rand_core::RngCore;
15use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
16use zeroize::Zeroize;
17
18pub mod coords;
19
20/// Elliptic curve
21///
22/// This trait contains all the low-level curve implementation logic: scalar, point arithmetics,
23/// encoding and etc.
24pub trait Curve: Debug + Copy + Eq + Ord + Hash + Default + Sync + Send + 'static {
25    /// Curve name
26    const CURVE_NAME: &'static str;
27
28    /// Type that represents a curve point
29    type Point: Additive
30        + From<CurveGenerator>
31        + Zero
32        + Zeroize
33        + OnCurve
34        + SmallFactor
35        + Copy
36        + Eq
37        + ConstantTimeEq
38        + ConditionallySelectable
39        + Default
40        + CompressedEncoding<Bytes = Self::CompressedPointArray>
41        + UncompressedEncoding<Bytes = Self::UncompressedPointArray>
42        + Decode
43        + Unpin
44        + Sync
45        + Send;
46    /// Type that represents a curve scalar
47    type Scalar: Additive
48        + Multiplicative<Self::Scalar, Output = Self::Scalar>
49        + Multiplicative<CurveGenerator, Output = Self::Point>
50        + Multiplicative<Self::Point, Output = Self::Point>
51        + Invertible
52        + Zero
53        + One
54        + Samplable
55        + Zeroize
56        + Copy
57        + Eq
58        + ConstantTimeEq
59        + ConditionallySelectable
60        + Default
61        + IntegerEncoding<Bytes = Self::ScalarArray>
62        + Unpin
63        + Sync
64        + Send;
65
66    /// Byte array that fits the whole bytes representation of compressed point
67    type CompressedPointArray: ByteArray;
68    /// Byte array that fits the whole bytes representation of uncompressed point
69    type UncompressedPointArray: ByteArray;
70    /// Byte array that fits the whole bytes representation of a scalar
71    type ScalarArray: ByteArray;
72    /// Byte array that fits the whole bytes representation of a coordinate
73    ///
74    /// If a curve doesn't expose point coordinates, it may be `[u8; 0]`
75    type CoordinateArray: ByteArray;
76}
77
78/// Type for which addition is defined
79pub trait Additive {
80    /// Computes `a + b`
81    fn add(a: &Self, b: &Self) -> Self;
82    /// Computes `a - b`
83    fn sub(a: &Self, b: &Self) -> Self;
84    /// Computes `-a`
85    fn negate(x: &Self) -> Self;
86
87    /// Takes `x`, returns `x + x`
88    ///
89    /// This can be more efficient than calling [`Self::add(x, x)`](Self::add)
90    fn double(x: &Self) -> Self
91    where
92        Self: Sized,
93    {
94        Self::add(x, x)
95    }
96}
97
98/// Type for which multiplication is defined
99pub trait Multiplicative<Rhs> {
100    /// Type of multiplication output
101    type Output;
102    /// Computes `a * b`
103    fn mul(a: &Self, b: &Rhs) -> Self::Output;
104}
105
106/// Type for which invert function is defined
107pub trait Invertible
108where
109    Self: Sized,
110{
111    /// Inverts $x$, returns $x^{-1}$ such that $x \cdot x^{-1} = 1$
112    fn invert(x: &Self) -> CtOption<Self>;
113}
114
115/// Type that has zero value (additive identity)
116pub trait Zero {
117    /// Constructs zero value of `Self`
118    fn zero() -> Self;
119    /// Checks (in constant-time) if `x` is zero
120    fn is_zero(x: &Self) -> Choice;
121}
122
123/// Type that has "one" value (multiplicative identity)
124pub trait One {
125    /// Constructs one value of `Self`
126    fn one() -> Self;
127    /// Checks (in constant-time) if `x` is one
128    fn is_one(x: &Self) -> Choice;
129}
130
131/// Type can be uniformely sampled from source of randomness
132pub trait Samplable {
133    /// Uniformely samples a random value of `Self`
134    fn random<R: RngCore>(rng: &mut R) -> Self;
135}
136
137/// Checks whether the point is on curve
138pub trait OnCurve {
139    /// Checks whether the point is on curve
140    fn is_on_curve(&self) -> Choice;
141}
142
143/// Checks whether a point has small factor
144pub trait SmallFactor {
145    /// Checks whether a point has no small factor
146    fn is_torsion_free(&self) -> Choice;
147}
148
149/// Curve generator
150///
151/// Represents a curve generator. The curve point must implement `From<CurveGenerator>`.
152/// The curve scalar can be multiplied at `CurveGenerator`, implementation may be
153/// more efficient than a generic multiplication.
154pub struct CurveGenerator;
155
156/// Compressed encoding of the point
157pub trait CompressedEncoding
158where
159    Self: Sized,
160{
161    /// Byte array that fits the whole compressed point representation
162    type Bytes: ByteArray;
163
164    /// Encodes the point as bytes in compressed form
165    fn to_bytes_compressed(&self) -> Self::Bytes;
166}
167
168/// Uncompressed encoding of the point
169pub trait UncompressedEncoding
170where
171    Self: Sized,
172{
173    /// Byte array that fits the whole uncompressed point representation
174    type Bytes: ByteArray;
175
176    /// Encodes the point as bytes in uncompressed form
177    ///
178    /// Some curves may not have such thing as compressed and uncompressed forms.
179    /// For these curves, we `CompressedEncoding` and `UncompressedEncoding` should
180    /// return the same encoding.
181    fn to_bytes_uncompressed(&self) -> Self::Bytes;
182}
183
184/// Encodes an integer as bytes
185pub trait IntegerEncoding
186where
187    Self: Sized,
188{
189    /// Byte array that fits the whole encoded integer
190    type Bytes: ByteArray;
191
192    /// Encodes integer as bytes in big-endian byte order
193    fn to_be_bytes(&self) -> Self::Bytes;
194    /// Encodes integer as bytes in little-endian byte order
195    fn to_le_bytes(&self) -> Self::Bytes;
196
197    /// Decodes integer encoded as bytes in big-endian bytes order
198    ///
199    /// Returns `None` if the bytes don't correspond to a valid integer.
200    fn from_be_bytes_exact(bytes: &Self::Bytes) -> Option<Self>;
201    /// Decodes integer encoded as bytes in little-endian bytes order
202    ///
203    /// Returns `None` if the bytes don't correspond to a valid integer.
204    fn from_le_bytes_exact(bytes: &Self::Bytes) -> Option<Self>;
205
206    /// Interprets `bytes` as big-endian encoding of an integer. Returns integer mod curve (prime) order.
207    fn from_be_bytes_mod_order(bytes: &[u8]) -> Self;
208    /// Interprets `bytes` as little-endian encoding of an integer. Returns integer mod curve (prime) order.
209    fn from_le_bytes_mod_order(bytes: &[u8]) -> Self;
210}
211
212/// Decodes a point from its compressed or uncompressed representation
213pub trait Decode: Sized {
214    /// Decodes a point from its compressed or uncompressed representation
215    fn decode(bytes: &[u8]) -> Option<Self>;
216}
217
218/// Error type
219pub struct Error;
220
221/// Byte array
222pub trait ByteArray: AsRef<[u8]> + AsMut<[u8]> + Clone + Send + Sync + 'static {
223    /// New byte array of zeroes
224    ///
225    /// Alternative to [`Default`] that is not implemented for generic `[T; N]`
226    /// (see [tracking issue](https://github.com/rust-lang/rust/issues/61415))
227    fn zeroes() -> Self;
228}
229
230impl<const N: usize> ByteArray for [u8; N] {
231    fn zeroes() -> Self {
232        [0; N]
233    }
234}
235
236impl<N: ArrayLength<u8>> ByteArray for GenericArray<u8, N> {
237    fn zeroes() -> Self {
238        GenericArray::default()
239    }
240}
241
242/// Reduces an integer represented as array of `N` bytes modulo curve (prime) order
243pub trait Reduce<const N: usize> {
244    /// Interprets `bytes` as big-endian encoding of an integer, returns this
245    /// integer modulo curve (prime) order
246    fn from_be_array_mod_order(bytes: &[u8; N]) -> Self;
247    /// Interprets `bytes` as little-endian encoding of an integer, returns this
248    /// integer modulo curve (prime) order
249    fn from_le_array_mod_order(bytes: &[u8; N]) -> Self;
250}
251
252/// Marker trait for curves whose underlying implementation doesn't allow
253/// representing invalid points.
254/// # Safety
255/// Safe to implement when the checks for valid points always return `true`.
256/// Those checks are:
257/// - [`OnCurve::is_on_curve`]
258/// - [`SmallFactor::is_torsion_free`]
259pub unsafe trait NoInvalidPoints {}