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 {}