crypto_bigint/traits.rs
1//! Traits provided by this crate
2
3use crate::{Limb, NonZero};
4use core::fmt::Debug;
5use core::ops::{BitAnd, BitOr, BitXor, Div, Not, Rem, Shl, Shr};
6use subtle::{
7 Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
8 CtOption,
9};
10
11#[cfg(feature = "rand_core")]
12use rand_core::CryptoRngCore;
13
14/// Integer type.
15pub trait Integer:
16 'static
17 + AsRef<[Limb]>
18 + BitAnd<Output = Self>
19 + BitOr<Output = Self>
20 + BitXor<Output = Self>
21 + for<'a> CheckedAdd<&'a Self, Output = Self>
22 + for<'a> CheckedSub<&'a Self, Output = Self>
23 + for<'a> CheckedMul<&'a Self, Output = Self>
24 + Copy
25 + ConditionallySelectable
26 + ConstantTimeEq
27 + ConstantTimeGreater
28 + ConstantTimeLess
29 + Debug
30 + Default
31 + Div<NonZero<Self>, Output = Self>
32 + Eq
33 + From<u64>
34 + Not
35 + Ord
36 + Rem<NonZero<Self>, Output = Self>
37 + Send
38 + Sized
39 + Shl<usize, Output = Self>
40 + Shr<usize, Output = Self>
41 + Sync
42 + Zero
43{
44 /// The value `1`.
45 const ONE: Self;
46
47 /// Maximum value this integer can express.
48 const MAX: Self;
49
50 /// Total size of the represented integer in bits.
51 const BITS: usize;
52
53 /// Total size of the represented integer in bytes.
54 const BYTES: usize;
55
56 /// The number of limbs used on this platform.
57 const LIMBS: usize;
58
59 /// Is this integer value an odd number?
60 ///
61 /// # Returns
62 ///
63 /// If odd, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
64 fn is_odd(&self) -> Choice;
65
66 /// Is this integer value an even number?
67 ///
68 /// # Returns
69 ///
70 /// If even, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
71 fn is_even(&self) -> Choice {
72 !self.is_odd()
73 }
74}
75
76/// Zero values.
77pub trait Zero: ConstantTimeEq + Sized {
78 /// The value `0`.
79 const ZERO: Self;
80
81 /// Determine if this value is equal to zero.
82 ///
83 /// # Returns
84 ///
85 /// If zero, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
86 fn is_zero(&self) -> Choice {
87 self.ct_eq(&Self::ZERO)
88 }
89}
90
91/// Random number generation support.
92#[cfg(feature = "rand_core")]
93pub trait Random: Sized {
94 /// Generate a cryptographically secure random value.
95 fn random(rng: &mut impl CryptoRngCore) -> Self;
96}
97
98/// Modular random number generation support.
99#[cfg(feature = "rand_core")]
100pub trait RandomMod: Sized + Zero {
101 /// Generate a cryptographically secure random number which is less than
102 /// a given `modulus`.
103 ///
104 /// This function uses rejection sampling, a method which produces an
105 /// unbiased distribution of in-range values provided the underlying
106 /// CSRNG is unbiased, but runs in variable-time.
107 ///
108 /// The variable-time nature of the algorithm should not pose a security
109 /// issue so long as the underlying random number generator is truly a
110 /// CSRNG, where previous outputs are unrelated to subsequent
111 /// outputs and do not reveal information about the RNG's internal state.
112 fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self;
113}
114
115/// Compute `self + rhs mod p`.
116pub trait AddMod<Rhs = Self> {
117 /// Output type.
118 type Output;
119
120 /// Compute `self + rhs mod p`.
121 ///
122 /// Assumes `self` and `rhs` are `< p`.
123 fn add_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
124}
125
126/// Compute `self - rhs mod p`.
127pub trait SubMod<Rhs = Self> {
128 /// Output type.
129 type Output;
130
131 /// Compute `self - rhs mod p`.
132 ///
133 /// Assumes `self` and `rhs` are `< p`.
134 fn sub_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
135}
136
137/// Compute `-self mod p`.
138pub trait NegMod {
139 /// Output type.
140 type Output;
141
142 /// Compute `-self mod p`.
143 #[must_use]
144 fn neg_mod(&self, p: &Self) -> Self::Output;
145}
146
147/// Compute `self * rhs mod p`.
148///
149/// Requires `p_inv = -(p^{-1} mod 2^{BITS}) mod 2^{BITS}` to be provided for efficiency.
150pub trait MulMod<Rhs = Self> {
151 /// Output type.
152 type Output;
153
154 /// Compute `self * rhs mod p`.
155 ///
156 /// Requires `p_inv = -(p^{-1} mod 2^{BITS}) mod 2^{BITS}` to be provided for efficiency.
157 fn mul_mod(&self, rhs: &Rhs, p: &Self, p_inv: Limb) -> Self::Output;
158}
159
160/// Checked addition.
161pub trait CheckedAdd<Rhs = Self>: Sized {
162 /// Output type.
163 type Output;
164
165 /// Perform checked subtraction, returning a [`CtOption`] which `is_some`
166 /// only if the operation did not overflow.
167 fn checked_add(&self, rhs: Rhs) -> CtOption<Self>;
168}
169
170/// Checked multiplication.
171pub trait CheckedMul<Rhs = Self>: Sized {
172 /// Output type.
173 type Output;
174
175 /// Perform checked multiplication, returning a [`CtOption`] which `is_some`
176 /// only if the operation did not overflow.
177 fn checked_mul(&self, rhs: Rhs) -> CtOption<Self>;
178}
179
180/// Checked subtraction.
181pub trait CheckedSub<Rhs = Self>: Sized {
182 /// Output type.
183 type Output;
184
185 /// Perform checked subtraction, returning a [`CtOption`] which `is_some`
186 /// only if the operation did not underflow.
187 fn checked_sub(&self, rhs: Rhs) -> CtOption<Self>;
188}
189
190/// Concatenate two numbers into a "wide" double-width value, using the `lo`
191/// value as the least significant value.
192pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
193 /// Concatenated output: twice the width of `Self`.
194 type Output;
195
196 /// Concatenate the two halves, with `self` as most significant and `lo`
197 /// as the least significant.
198 fn concat(&self, lo: &Self) -> Self::Output {
199 self.concat_mixed(lo)
200 }
201}
202
203/// Concatenate two numbers into a "wide" combined-width value, using the `lo`
204/// value as the least significant value.
205pub trait ConcatMixed<Lo: ?Sized = Self> {
206 /// Concatenated output: combination of `Lo` and `Self`.
207 type MixedOutput;
208
209 /// Concatenate the two values, with `self` as most significant and `lo`
210 /// as the least significant.
211 fn concat_mixed(&self, lo: &Lo) -> Self::MixedOutput;
212}
213
214/// Split a number in half, returning the most significant half followed by
215/// the least significant.
216pub trait Split: SplitMixed<Self::Output, Self::Output> {
217 /// Split output: high/low components of the value.
218 type Output;
219
220 /// Split this number in half, returning its high and low components
221 /// respectively.
222 fn split(&self) -> (Self::Output, Self::Output) {
223 self.split_mixed()
224 }
225}
226
227/// Split a number into parts, returning the most significant part followed by
228/// the least significant.
229pub trait SplitMixed<Hi, Lo> {
230 /// Split this number into parts, returning its high and low components
231 /// respectively.
232 fn split_mixed(&self) -> (Hi, Lo);
233}
234
235/// Integers whose representation takes a bounded amount of space.
236pub trait Bounded {
237 /// Size of this integer in bits.
238 const BITS: usize;
239
240 /// Size of this integer in bytes.
241 const BYTES: usize;
242}
243
244/// Encoding support.
245pub trait Encoding: Sized {
246 /// Byte array representation.
247 type Repr: AsRef<[u8]> + AsMut<[u8]> + Copy + Clone + Sized;
248
249 /// Decode from big endian bytes.
250 fn from_be_bytes(bytes: Self::Repr) -> Self;
251
252 /// Decode from little endian bytes.
253 fn from_le_bytes(bytes: Self::Repr) -> Self;
254
255 /// Encode to big endian bytes.
256 fn to_be_bytes(&self) -> Self::Repr;
257
258 /// Encode to little endian bytes.
259 fn to_le_bytes(&self) -> Self::Repr;
260}
261
262/// Support for optimized squaring
263pub trait Square: Sized
264where
265 for<'a> &'a Self: core::ops::Mul<&'a Self, Output = Self>,
266{
267 /// Computes the same as `self.mul(self)`, but may be more efficient.
268 fn square(&self) -> Self {
269 self * self
270 }
271}
272
273/// Constant-time exponentiation.
274pub trait Pow<Exponent> {
275 /// Raises to the `exponent` power.
276 fn pow(&self, exponent: &Exponent) -> Self;
277}
278
279impl<T: PowBoundedExp<Exponent>, Exponent: Bounded> Pow<Exponent> for T {
280 fn pow(&self, exponent: &Exponent) -> Self {
281 self.pow_bounded_exp(exponent, Exponent::BITS)
282 }
283}
284
285/// Constant-time exponentiation with exponent of a bounded bit size.
286pub trait PowBoundedExp<Exponent> {
287 /// Raises to the `exponent` power,
288 /// with `exponent_bits` representing the number of (least significant) bits
289 /// to take into account for the exponent.
290 ///
291 /// NOTE: `exponent_bits` may be leaked in the time pattern.
292 fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: usize) -> Self;
293}
294
295/// Performs modular multi-exponentiation using Montgomery's ladder.
296///
297/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
298pub trait MultiExponentiate<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
299where
300 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
301{
302 /// Calculates `x1 ^ k1 * ... * xn ^ kn`.
303 fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self;
304}
305
306impl<T, Exponent, BasesAndExponents> MultiExponentiate<Exponent, BasesAndExponents> for T
307where
308 T: MultiExponentiateBoundedExp<Exponent, BasesAndExponents>,
309 Exponent: Bounded,
310 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
311{
312 fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self {
313 Self::multi_exponentiate_bounded_exp(bases_and_exponents, Exponent::BITS)
314 }
315}
316
317/// Performs modular multi-exponentiation using Montgomery's ladder.
318/// `exponent_bits` represents the number of bits to take into account for the exponent.
319///
320/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
321///
322/// NOTE: this value is leaked in the time pattern.
323pub trait MultiExponentiateBoundedExp<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
324where
325 BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
326{
327 /// Calculates `x1 ^ k1 * ... * xn ^ kn`.
328 fn multi_exponentiate_bounded_exp(
329 bases_and_exponents: &BasesAndExponents,
330 exponent_bits: usize,
331 ) -> Self;
332}
333
334/// Constant-time inversion.
335pub trait Invert: Sized {
336 /// Output of the inversion.
337 type Output;
338
339 /// Computes the inverse.
340 fn invert(&self) -> Self::Output;
341}