//! Traits provided by this crate use crate::{Limb, NonZero}; use core::fmt::Debug; use core::ops::{BitAnd, BitOr, BitXor, Div, Not, Rem, Shl, Shr}; use subtle::{ Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess, CtOption, }; #[cfg(feature = "rand_core")] use rand_core::CryptoRngCore; /// Integer type. pub trait Integer: 'static + AsRef<[Limb]> + BitAnd + BitOr + BitXor + for<'a> CheckedAdd<&'a Self, Output = Self> + for<'a> CheckedSub<&'a Self, Output = Self> + for<'a> CheckedMul<&'a Self, Output = Self> + Copy + ConditionallySelectable + ConstantTimeEq + ConstantTimeGreater + ConstantTimeLess + Debug + Default + Div, Output = Self> + Eq + From + Not + Ord + Rem, Output = Self> + Send + Sized + Shl + Shr + Sync + Zero { /// The value `1`. const ONE: Self; /// Maximum value this integer can express. const MAX: Self; /// Total size of the represented integer in bits. const BITS: usize; /// Total size of the represented integer in bytes. const BYTES: usize; /// The number of limbs used on this platform. const LIMBS: usize; /// Is this integer value an odd number? /// /// # Returns /// /// If odd, returns `Choice(1)`. Otherwise, returns `Choice(0)`. fn is_odd(&self) -> Choice; /// Is this integer value an even number? /// /// # Returns /// /// If even, returns `Choice(1)`. Otherwise, returns `Choice(0)`. fn is_even(&self) -> Choice { !self.is_odd() } } /// Zero values. pub trait Zero: ConstantTimeEq + Sized { /// The value `0`. const ZERO: Self; /// Determine if this value is equal to zero. /// /// # Returns /// /// If zero, returns `Choice(1)`. Otherwise, returns `Choice(0)`. fn is_zero(&self) -> Choice { self.ct_eq(&Self::ZERO) } } /// Random number generation support. #[cfg(feature = "rand_core")] pub trait Random: Sized { /// Generate a cryptographically secure random value. fn random(rng: &mut impl CryptoRngCore) -> Self; } /// Modular random number generation support. #[cfg(feature = "rand_core")] pub trait RandomMod: Sized + Zero { /// Generate a cryptographically secure random number which is less than /// a given `modulus`. /// /// This function uses rejection sampling, a method which produces an /// unbiased distribution of in-range values provided the underlying /// CSRNG is unbiased, but runs in variable-time. /// /// The variable-time nature of the algorithm should not pose a security /// issue so long as the underlying random number generator is truly a /// CSRNG, where previous outputs are unrelated to subsequent /// outputs and do not reveal information about the RNG's internal state. fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero) -> Self; } /// Compute `self + rhs mod p`. pub trait AddMod { /// Output type. type Output; /// Compute `self + rhs mod p`. /// /// Assumes `self` and `rhs` are `< p`. fn add_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output; } /// Compute `self - rhs mod p`. pub trait SubMod { /// Output type. type Output; /// Compute `self - rhs mod p`. /// /// Assumes `self` and `rhs` are `< p`. fn sub_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output; } /// Compute `-self mod p`. pub trait NegMod { /// Output type. type Output; /// Compute `-self mod p`. #[must_use] fn neg_mod(&self, p: &Self) -> Self::Output; } /// Compute `self * rhs mod p`. /// /// Requires `p_inv = -(p^{-1} mod 2^{BITS}) mod 2^{BITS}` to be provided for efficiency. pub trait MulMod { /// Output type. type Output; /// Compute `self * rhs mod p`. /// /// Requires `p_inv = -(p^{-1} mod 2^{BITS}) mod 2^{BITS}` to be provided for efficiency. fn mul_mod(&self, rhs: &Rhs, p: &Self, p_inv: Limb) -> Self::Output; } /// Checked addition. pub trait CheckedAdd: Sized { /// Output type. type Output; /// Perform checked subtraction, returning a [`CtOption`] which `is_some` /// only if the operation did not overflow. fn checked_add(&self, rhs: Rhs) -> CtOption; } /// Checked multiplication. pub trait CheckedMul: Sized { /// Output type. type Output; /// Perform checked multiplication, returning a [`CtOption`] which `is_some` /// only if the operation did not overflow. fn checked_mul(&self, rhs: Rhs) -> CtOption; } /// Checked subtraction. pub trait CheckedSub: Sized { /// Output type. type Output; /// Perform checked subtraction, returning a [`CtOption`] which `is_some` /// only if the operation did not underflow. fn checked_sub(&self, rhs: Rhs) -> CtOption; } /// Concatenate two numbers into a "wide" double-width value, using the `lo` /// value as the least significant value. pub trait Concat: ConcatMixed { /// Concatenated output: twice the width of `Self`. type Output; /// Concatenate the two halves, with `self` as most significant and `lo` /// as the least significant. fn concat(&self, lo: &Self) -> Self::Output { self.concat_mixed(lo) } } /// Concatenate two numbers into a "wide" combined-width value, using the `lo` /// value as the least significant value. pub trait ConcatMixed { /// Concatenated output: combination of `Lo` and `Self`. type MixedOutput; /// Concatenate the two values, with `self` as most significant and `lo` /// as the least significant. fn concat_mixed(&self, lo: &Lo) -> Self::MixedOutput; } /// Split a number in half, returning the most significant half followed by /// the least significant. pub trait Split: SplitMixed { /// Split output: high/low components of the value. type Output; /// Split this number in half, returning its high and low components /// respectively. fn split(&self) -> (Self::Output, Self::Output) { self.split_mixed() } } /// Split a number into parts, returning the most significant part followed by /// the least significant. pub trait SplitMixed { /// Split this number into parts, returning its high and low components /// respectively. fn split_mixed(&self) -> (Hi, Lo); } /// Integers whose representation takes a bounded amount of space. pub trait Bounded { /// Size of this integer in bits. const BITS: usize; /// Size of this integer in bytes. const BYTES: usize; } /// Encoding support. pub trait Encoding: Sized { /// Byte array representation. type Repr: AsRef<[u8]> + AsMut<[u8]> + Copy + Clone + Sized; /// Decode from big endian bytes. fn from_be_bytes(bytes: Self::Repr) -> Self; /// Decode from little endian bytes. fn from_le_bytes(bytes: Self::Repr) -> Self; /// Encode to big endian bytes. fn to_be_bytes(&self) -> Self::Repr; /// Encode to little endian bytes. fn to_le_bytes(&self) -> Self::Repr; } /// Support for optimized squaring pub trait Square: Sized where for<'a> &'a Self: core::ops::Mul<&'a Self, Output = Self>, { /// Computes the same as `self.mul(self)`, but may be more efficient. fn square(&self) -> Self { self * self } } /// Constant-time exponentiation. pub trait Pow { /// Raises to the `exponent` power. fn pow(&self, exponent: &Exponent) -> Self; } impl, Exponent: Bounded> Pow for T { fn pow(&self, exponent: &Exponent) -> Self { self.pow_bounded_exp(exponent, Exponent::BITS) } } /// Constant-time exponentiation with exponent of a bounded bit size. pub trait PowBoundedExp { /// Raises to the `exponent` power, /// with `exponent_bits` representing the number of (least significant) bits /// to take into account for the exponent. /// /// NOTE: `exponent_bits` may be leaked in the time pattern. fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: usize) -> Self; } /// Constant-time inversion. pub trait Invert: Sized { /// Output of the inversion. type Output; /// Computes the inverse. fn invert(&self) -> Self::Output; }