rustcrypto_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::convert::Infallible;
13use core::fmt;
14use core::iter::Sum;
15use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
16use ff::PrimeField;
17use rand_core::{RngCore, TryRngCore};
18use subtle::{Choice, CtOption};
19
20pub mod cofactor;
21pub mod prime;
22#[cfg(feature = "tests")]
23pub mod tests;
24
25#[cfg(feature = "alloc")]
26mod wnaf;
27#[cfg(feature = "alloc")]
28pub use self::wnaf::{Wnaf, WnafBase, WnafGroup, WnafScalar};
29
30/// A helper trait for types with a group operation.
31pub trait GroupOps<Rhs = Self, Output = Self>:
32 Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
33{
34}
35
36impl<T, Rhs, Output> GroupOps<Rhs, Output> for T where
37 T: Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
38{
39}
40
41/// A helper trait for references with a group operation.
42pub trait GroupOpsOwned<Rhs = Self, Output = Self>: for<'r> GroupOps<&'r Rhs, Output> {}
43impl<T, Rhs, Output> GroupOpsOwned<Rhs, Output> for T where T: for<'r> GroupOps<&'r Rhs, Output> {}
44
45/// A helper trait for types implementing group scalar multiplication.
46pub trait ScalarMul<Rhs, Output = Self>: Mul<Rhs, Output = Output> + MulAssign<Rhs> {}
47
48impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Output> + MulAssign<Rhs>
49{}
50
51/// A helper trait for references implementing group scalar multiplication.
52pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
53impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
54
55/// This trait represents an element of a cryptographic group.
56pub trait Group:
57 Clone
58 + Copy
59 + fmt::Debug
60 + Eq
61 + Sized
62 + Send
63 + Sync
64 + 'static
65 + Sum
66 + for<'a> Sum<&'a Self>
67 + Neg<Output = Self>
68 + GroupOps
69 + GroupOpsOwned
70 + ScalarMul<<Self as Group>::Scalar>
71 + ScalarMulOwned<<Self as Group>::Scalar>
72{
73 /// Scalars modulo the order of this group's scalar field.
74 type Scalar: PrimeField;
75
76 /// Returns an element chosen uniformly at random from the non-identity elements of
77 /// this group.
78 ///
79 /// This function is non-deterministic, and samples from the user-provided RNG.
80 fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
81 Self::try_from_rng(rng)
82 .map_err(|e: Infallible| e)
83 .expect("Infallible failed")
84
85 // NOTE: once MSRV gets to 1.82 remove the map_err/expect and use
86 // let Ok(out) = Self::try_from_rng(rng);
87 // out
88 // See: https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#omitting-empty-types-in-pattern-matching
89 }
90
91 /// Returns an element chosen uniformly at random from the non-identity elements of
92 /// this group.
93 ///
94 /// This function is non-deterministic, and samples from the user-provided RNG.
95 fn try_from_rng<R: TryRngCore + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
96
97 /// Returns the additive identity, also known as the "neutral element".
98 fn identity() -> Self;
99
100 /// Returns a fixed generator of the prime-order subgroup.
101 fn generator() -> Self;
102
103 /// Determines if this point is the identity.
104 fn is_identity(&self) -> Choice;
105
106 /// Doubles this element.
107 #[must_use]
108 fn double(&self) -> Self;
109
110 /// Multiply by the generator of the prime-order subgroup.
111 #[must_use]
112 fn mul_by_generator(scalar: &Self::Scalar) -> Self {
113 Self::generator() * scalar
114 }
115}
116
117/// Efficient representation of an elliptic curve point guaranteed.
118pub trait Curve:
119 Group + GroupOps<<Self as Curve>::AffineRepr> + GroupOpsOwned<<Self as Curve>::AffineRepr>
120{
121 /// The affine representation for this elliptic curve.
122 type AffineRepr;
123
124 /// Converts a batch of projective elements into affine elements. This function will
125 /// panic if `p.len() != q.len()`.
126 fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) {
127 assert_eq!(p.len(), q.len());
128
129 for (p, q) in p.iter().zip(q.iter_mut()) {
130 *q = p.to_affine();
131 }
132 }
133
134 /// Converts this element into its affine representation.
135 fn to_affine(&self) -> Self::AffineRepr;
136}
137
138pub trait GroupEncoding: Sized {
139 /// The encoding of group elements.
140 ///
141 /// The `Default` implementation is not required to return a valid point encoding. The
142 /// bound is present to enable encodings to be constructed generically:
143 /// ```
144 /// # use rustcrypto_group::GroupEncoding;
145 /// # use subtle::CtOption;
146 /// # struct G;
147 /// # impl GroupEncoding for G {
148 /// # type Repr = [u8; 0];
149 /// # fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> { unimplemented!() }
150 /// # fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> { unimplemented!() }
151 /// # fn to_bytes(&self) -> Self::Repr { unimplemented!() }
152 /// # }
153 /// # let buf = &[0u8; 0][..];
154 /// let mut encoding = <G as GroupEncoding>::Repr::default();
155 /// encoding.as_mut().copy_from_slice(buf);
156 /// ```
157 ///
158 /// It is recommended that the default should be the all-zeroes encoding.
159 type Repr: Copy + Default + Send + Sync + 'static + AsRef<[u8]> + AsMut<[u8]>;
160
161 /// Attempts to deserialize a group element from its encoding.
162 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self>;
163
164 /// Attempts to deserialize a group element, not checking if the element is valid.
165 ///
166 /// **This is dangerous to call unless you trust the bytes you are reading; otherwise,
167 /// API invariants may be broken.** Please consider using
168 /// [`GroupEncoding::from_bytes`] instead.
169 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self>;
170
171 /// Converts this element into its byte encoding. This may or may not support
172 /// encoding the identity.
173 // TODO: Figure out how to handle identity encoding generically.
174 fn to_bytes(&self) -> Self::Repr;
175}
176
177/// Affine representation of a point on an elliptic curve that has a defined uncompressed
178/// encoding.
179pub trait UncompressedEncoding: Sized {
180 type Uncompressed: Default + AsRef<[u8]> + AsMut<[u8]>;
181
182 /// Attempts to deserialize an element from its uncompressed encoding.
183 fn from_uncompressed(bytes: &Self::Uncompressed) -> CtOption<Self>;
184
185 /// Attempts to deserialize an uncompressed element, not checking if the element is in
186 /// the correct subgroup.
187 ///
188 /// **This is dangerous to call unless you trust the bytes you are reading; otherwise,
189 /// API invariants may be broken.** Please consider using
190 /// [`UncompressedEncoding::from_uncompressed`] instead.
191 fn from_uncompressed_unchecked(bytes: &Self::Uncompressed) -> CtOption<Self>;
192
193 /// Converts this element into its uncompressed encoding, so long as it's not
194 /// the point at infinity.
195 fn to_uncompressed(&self) -> Self::Uncompressed;
196}