group/lib.rs
1#![no_std]
2// Catch documentation errors caused by code changes.
3#![deny(rustdoc::broken_intra_doc_links)]
4
5#[cfg(feature = "alloc")]
6#[macro_use]
7extern crate alloc;
8
9// Re-export ff to make version-matching easier.
10pub use ff;
11
12use core::fmt;
13use core::iter::Sum;
14use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
15use ff::PrimeField;
16use rand_core::{Rng, TryRng};
17use subtle::{Choice, CtOption};
18
19pub mod cofactor;
20pub mod prime;
21#[cfg(feature = "tests")]
22pub mod tests;
23
24#[cfg(feature = "alloc")]
25mod wnaf;
26#[cfg(feature = "alloc")]
27pub use self::wnaf::{Wnaf, WnafBase, WnafGroup, WnafScalar};
28
29/// A helper trait for types with a group operation.
30pub trait GroupOps<Rhs = Self, Output = Self>:
31 Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
32{
33}
34
35impl<T, Rhs, Output> GroupOps<Rhs, Output> for T where
36 T: Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
37{
38}
39
40/// A helper trait for references with a group operation.
41pub trait GroupOpsOwned<Rhs = Self, Output = Self>: for<'r> GroupOps<&'r Rhs, Output> {}
42impl<T, Rhs, Output> GroupOpsOwned<Rhs, Output> for T where T: for<'r> GroupOps<&'r Rhs, Output> {}
43
44/// A helper trait for types implementing group scalar multiplication.
45pub trait ScalarMul<Rhs, Output = Self>: Mul<Rhs, Output = Output> + MulAssign<Rhs> {}
46
47impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Output> + MulAssign<Rhs>
48{}
49
50/// A helper trait for references implementing group scalar multiplication.
51pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
52impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
53
54/// This trait represents an element of a cryptographic group.
55pub trait Group:
56 Clone
57 + Copy
58 + fmt::Debug
59 + Eq
60 + Sized
61 + Send
62 + Sync
63 + 'static
64 + Sum
65 + for<'a> Sum<&'a Self>
66 + Neg<Output = Self>
67 + GroupOps
68 + GroupOpsOwned
69 + ScalarMul<<Self as Group>::Scalar>
70 + ScalarMulOwned<<Self as Group>::Scalar>
71{
72 /// Scalars modulo the order of this group's scalar field.
73 type Scalar: PrimeField;
74
75 /// Returns an element chosen uniformly at random from the non-identity elements of
76 /// this group using a user-provided infallible RNG.
77 ///
78 /// This is a convenience wrapper around [`Group::try_random`] for RNGs that cannot
79 /// fail. Use [`Group::try_random`] if your RNG may fail (for example, an OS-backed
80 /// entropy source).
81 fn random<R: Rng + ?Sized>(rng: &mut R) -> Self {
82 let Ok(out) = Self::try_random(rng);
83 out
84 }
85
86 /// Returns an element chosen uniformly at random from the non-identity elements of
87 /// this group using a user-provided fallible RNG.
88 ///
89 /// Returns `Err` propagating the RNG's error if the underlying RNG fails to produce
90 /// the randomness required to sample an element. Implementors of `Group` must
91 /// provide this method; [`Group::random`] is derived from it for infallible RNGs.
92 fn try_random<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
93
94 /// Returns the additive identity, also known as the "neutral element".
95 fn identity() -> Self;
96
97 /// Returns a fixed generator of the prime-order subgroup.
98 fn generator() -> Self;
99
100 /// Determines if this point is the identity.
101 fn is_identity(&self) -> Choice;
102
103 /// Doubles this element.
104 #[must_use]
105 fn double(&self) -> Self;
106
107 /// Multiply by the generator of the prime-order subgroup.
108 #[must_use]
109 fn mul_by_generator(scalar: &Self::Scalar) -> Self {
110 Self::generator() * scalar
111 }
112}
113
114/// Efficient representation of an elliptic curve point.
115pub trait Curve: Group + GroupOps<Self::Affine> + GroupOpsOwned<Self::Affine> {
116 /// The affine representation for this elliptic curve.
117 type Affine: CurveAffine<Curve = Self, Scalar = Self::Scalar>;
118
119 /// Converts a batch of projective elements into affine elements. This function will
120 /// panic if `p.len() != q.len()`.
121 fn batch_normalize(p: &[Self], q: &mut [Self::Affine]) {
122 assert_eq!(p.len(), q.len());
123
124 for (p, q) in p.iter().zip(q.iter_mut()) {
125 *q = p.to_affine();
126 }
127 }
128
129 /// Converts this element into its affine representation.
130 fn to_affine(&self) -> Self::Affine;
131}
132
133/// Affine representation of an elliptic curve point.
134pub trait CurveAffine:
135 GroupEncoding
136 + Copy
137 + fmt::Debug
138 + Eq
139 + Send
140 + Sync
141 + 'static
142 + Neg<Output = Self>
143 + Mul<<Self::Curve as Group>::Scalar, Output = Self::Curve>
144 + for<'r> Mul<&'r <Self::Curve as Group>::Scalar, Output = Self::Curve>
145{
146 /// The efficient representation for this elliptic curve.
147 type Curve: Curve<Affine = Self, Scalar = Self::Scalar>;
148
149 /// Scalars modulo the order of this group's scalar field.
150 ///
151 /// This associated type is temporary, and will be removed once downstream users have
152 /// migrated to using `Curve` as the primary generic bound.
153 type Scalar: PrimeField;
154
155 /// Returns the additive identity.
156 fn identity() -> Self;
157
158 /// Returns a fixed generator of unknown exponent.
159 fn generator() -> Self;
160
161 /// Determines if this point represents the additive identity.
162 fn is_identity(&self) -> Choice;
163
164 /// Converts this affine point to its efficient representation.
165 fn to_curve(&self) -> Self::Curve;
166}
167
168pub trait GroupEncoding: Sized {
169 /// The encoding of group elements.
170 ///
171 /// The `Default` implementation is not required to return a valid point encoding. The
172 /// bound is present to enable encodings to be constructed generically:
173 /// ```
174 /// # use group::GroupEncoding;
175 /// # use subtle::CtOption;
176 /// # struct G;
177 /// # impl GroupEncoding for G {
178 /// # type Repr = [u8; 0];
179 /// # fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> { unimplemented!() }
180 /// # fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> { unimplemented!() }
181 /// # fn to_bytes(&self) -> Self::Repr { unimplemented!() }
182 /// # }
183 /// # let buf = &[0u8; 0][..];
184 /// let mut encoding = <G as GroupEncoding>::Repr::default();
185 /// encoding.as_mut().copy_from_slice(buf);
186 /// ```
187 ///
188 /// It is recommended that the default should be the all-zeroes encoding.
189 type Repr: Copy + Default + Send + Sync + 'static + AsRef<[u8]> + AsMut<[u8]>;
190
191 /// Attempts to deserialize a group element from its encoding.
192 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self>;
193
194 /// Attempts to deserialize a group element, not checking if the element is valid.
195 ///
196 /// **This is dangerous to call unless you trust the bytes you are reading; otherwise,
197 /// API invariants may be broken.** Please consider using
198 /// [`GroupEncoding::from_bytes`] instead.
199 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self>;
200
201 /// Converts this element into its byte encoding. This may or may not support
202 /// encoding the identity.
203 // TODO: Figure out how to handle identity encoding generically.
204 fn to_bytes(&self) -> Self::Repr;
205}
206
207/// Affine representation of a point on an elliptic curve that has a defined uncompressed
208/// encoding.
209pub trait UncompressedEncoding: Sized {
210 type Uncompressed: Default + AsRef<[u8]> + AsMut<[u8]>;
211
212 /// Attempts to deserialize an element from its uncompressed encoding.
213 fn from_uncompressed(bytes: &Self::Uncompressed) -> CtOption<Self>;
214
215 /// Attempts to deserialize an uncompressed element, not checking if the element is in
216 /// the correct subgroup.
217 ///
218 /// **This is dangerous to call unless you trust the bytes you are reading; otherwise,
219 /// API invariants may be broken.** Please consider using
220 /// [`UncompressedEncoding::from_uncompressed`] instead.
221 fn from_uncompressed_unchecked(bytes: &Self::Uncompressed) -> CtOption<Self>;
222
223 /// Converts this element into its uncompressed encoding, so long as it's not
224 /// the point at infinity.
225 fn to_uncompressed(&self) -> Self::Uncompressed;
226}