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::{CryptoRng, RngCore};
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 /// Is this integer value an odd number?
51 ///
52 /// # Returns
53 ///
54 /// If odd, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
55 fn is_odd(&self) -> Choice;
56
57 /// Is this integer value an even number?
58 ///
59 /// # Returns
60 ///
61 /// If even, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
62 fn is_even(&self) -> Choice {
63 !self.is_odd()
64 }
65}
66
67/// Zero values.
68pub trait Zero: ConstantTimeEq + Sized {
69 /// The value `0`.
70 const ZERO: Self;
71
72 /// Determine if this value is equal to zero.
73 ///
74 /// # Returns
75 ///
76 /// If zero, returns `Choice(1)`. Otherwise, returns `Choice(0)`.
77 fn is_zero(&self) -> Choice {
78 self.ct_eq(&Self::ZERO)
79 }
80}
81
82/// Random number generation support.
83#[cfg(feature = "rand_core")]
84#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
85pub trait Random: Sized {
86 /// Generate a cryptographically secure random value.
87 fn random(rng: impl CryptoRng + RngCore) -> Self;
88}
89
90/// Modular random number generation support.
91#[cfg(feature = "rand_core")]
92#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
93pub trait RandomMod: Sized + Zero {
94 /// Generate a cryptographically secure random number which is less than
95 /// a given `modulus`.
96 ///
97 /// This function uses rejection sampling, a method which produces an
98 /// unbiased distribution of in-range values provided the underlying
99 /// [`CryptoRng`] is unbiased, but runs in variable-time.
100 ///
101 /// The variable-time nature of the algorithm should not pose a security
102 /// issue so long as the underlying random number generator is truly a
103 /// [`CryptoRng`], where previous outputs are unrelated to subsequent
104 /// outputs and do not reveal information about the RNG's internal state.
105 fn random_mod(rng: impl CryptoRng + RngCore, modulus: &NonZero<Self>) -> Self;
106}
107
108/// Compute `self + rhs mod p`.
109pub trait AddMod<Rhs = Self> {
110 /// Output type.
111 type Output;
112
113 /// Compute `self + rhs mod p`.
114 ///
115 /// Assumes `self` and `rhs` are `< p`.
116 fn add_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
117}
118
119/// Compute `self - rhs mod p`.
120pub trait SubMod<Rhs = Self> {
121 /// Output type.
122 type Output;
123
124 /// Compute `self - rhs mod p`.
125 ///
126 /// Assumes `self` and `rhs` are `< p`.
127 fn sub_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
128}
129
130/// Compute `-self mod p`.
131pub trait NegMod {
132 /// Output type.
133 type Output;
134
135 /// Compute `-self mod p`.
136 #[must_use]
137 fn neg_mod(&self, p: &Self) -> Self::Output;
138}
139
140/// Compute `self * rhs mod p`.
141///
142/// Requires `p_inv = -(p^{-1} mod 2^{BITS}) mod 2^{BITS}` to be provided for efficiency.
143pub trait MulMod<Rhs = Self> {
144 /// Output type.
145 type Output;
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.
150 fn mul_mod(&self, rhs: &Rhs, p: &Self, p_inv: Limb) -> Self::Output;
151}
152
153/// Checked addition.
154pub trait CheckedAdd<Rhs = Self>: Sized {
155 /// Output type.
156 type Output;
157
158 /// Perform checked subtraction, returning a [`CtOption`] which `is_some`
159 /// only if the operation did not overflow.
160 fn checked_add(&self, rhs: Rhs) -> CtOption<Self>;
161}
162
163/// Checked multiplication.
164pub trait CheckedMul<Rhs = Self>: Sized {
165 /// Output type.
166 type Output;
167
168 /// Perform checked multiplication, returning a [`CtOption`] which `is_some`
169 /// only if the operation did not overflow.
170 fn checked_mul(&self, rhs: Rhs) -> CtOption<Self>;
171}
172
173/// Checked substraction.
174pub trait CheckedSub<Rhs = Self>: Sized {
175 /// Output type.
176 type Output;
177
178 /// Perform checked subtraction, returning a [`CtOption`] which `is_some`
179 /// only if the operation did not underflow.
180 fn checked_sub(&self, rhs: Rhs) -> CtOption<Self>;
181}
182
183/// Concatenate two numbers into a "wide" twice-width value, using the `rhs`
184/// value as the least significant value.
185pub trait Concat<Rhs = Self> {
186 /// Concatenated output: twice the width of `Self`.
187 type Output;
188
189 /// Concatenate the two values, with `self` as most significant and `rhs`
190 /// as the least significant.
191 fn concat(&self, rhs: &Self) -> Self::Output;
192}
193
194/// Split a number in half, returning the most significant half followed by
195/// the least significant.
196pub trait Split<Rhs = Self> {
197 /// Split output: high/low components of the value.
198 type Output;
199
200 /// Split this number in half, returning its high and low components
201 /// respectively.
202 fn split(&self) -> (Self::Output, Self::Output);
203}
204
205/// Encoding support.
206pub trait Encoding: Sized {
207 /// Size of this integer in bits.
208 const BIT_SIZE: usize;
209
210 /// Size of this integer in bytes.
211 const BYTE_SIZE: usize;
212
213 /// Byte array representation.
214 type Repr: AsRef<[u8]> + AsMut<[u8]> + Copy + Clone + Sized;
215
216 /// Decode from big endian bytes.
217 fn from_be_bytes(bytes: Self::Repr) -> Self;
218
219 /// Decode from little endian bytes.
220 fn from_le_bytes(bytes: Self::Repr) -> Self;
221
222 /// Encode to big endian bytes.
223 fn to_be_bytes(&self) -> Self::Repr;
224
225 /// Encode to little endian bytes.
226 fn to_le_bytes(&self) -> Self::Repr;
227}