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}