342 lines
9.9 KiB
Rust
342 lines
9.9 KiB
Rust
|
|
//! 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<Output = Self>
|
|||
|
|
+ BitOr<Output = Self>
|
|||
|
|
+ BitXor<Output = Self>
|
|||
|
|
+ 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<NonZero<Self>, Output = Self>
|
|||
|
|
+ Eq
|
|||
|
|
+ From<u64>
|
|||
|
|
+ Not
|
|||
|
|
+ Ord
|
|||
|
|
+ Rem<NonZero<Self>, Output = Self>
|
|||
|
|
+ Send
|
|||
|
|
+ Sized
|
|||
|
|
+ Shl<usize, Output = Self>
|
|||
|
|
+ Shr<usize, Output = Self>
|
|||
|
|
+ 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>) -> Self;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Compute `self + rhs mod p`.
|
|||
|
|
pub trait AddMod<Rhs = Self> {
|
|||
|
|
/// 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<Rhs = Self> {
|
|||
|
|
/// 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<Rhs = Self> {
|
|||
|
|
/// 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<Rhs = Self>: 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<Self>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Checked multiplication.
|
|||
|
|
pub trait CheckedMul<Rhs = Self>: 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<Self>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Checked subtraction.
|
|||
|
|
pub trait CheckedSub<Rhs = Self>: 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<Self>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Concatenate two numbers into a "wide" double-width value, using the `lo`
|
|||
|
|
/// value as the least significant value.
|
|||
|
|
pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
|
|||
|
|
/// 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<Lo: ?Sized = Self> {
|
|||
|
|
/// 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<Self::Output, Self::Output> {
|
|||
|
|
/// 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<Hi, Lo> {
|
|||
|
|
/// 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<Exponent> {
|
|||
|
|
/// Raises to the `exponent` power.
|
|||
|
|
fn pow(&self, exponent: &Exponent) -> Self;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
impl<T: PowBoundedExp<Exponent>, Exponent: Bounded> Pow<Exponent> 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<Exponent> {
|
|||
|
|
/// 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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Performs modular multi-exponentiation using Montgomery's ladder.
|
|||
|
|
///
|
|||
|
|
/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
|
|||
|
|
pub trait MultiExponentiate<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
|
|||
|
|
where
|
|||
|
|
BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
|
|||
|
|
{
|
|||
|
|
/// Calculates `x1 ^ k1 * ... * xn ^ kn`.
|
|||
|
|
fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
impl<T, Exponent, BasesAndExponents> MultiExponentiate<Exponent, BasesAndExponents> for T
|
|||
|
|
where
|
|||
|
|
T: MultiExponentiateBoundedExp<Exponent, BasesAndExponents>,
|
|||
|
|
Exponent: Bounded,
|
|||
|
|
BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
|
|||
|
|
{
|
|||
|
|
fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self {
|
|||
|
|
Self::multi_exponentiate_bounded_exp(bases_and_exponents, Exponent::BITS)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Performs modular multi-exponentiation using Montgomery's ladder.
|
|||
|
|
/// `exponent_bits` represents the number of bits to take into account for the exponent.
|
|||
|
|
///
|
|||
|
|
/// See: Straus, E. G. Problems and solutions: Addition chains of vectors. American Mathematical Monthly 71 (1964), 806–808.
|
|||
|
|
///
|
|||
|
|
/// NOTE: this value is leaked in the time pattern.
|
|||
|
|
pub trait MultiExponentiateBoundedExp<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
|
|||
|
|
where
|
|||
|
|
BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
|
|||
|
|
{
|
|||
|
|
/// Calculates `x1 ^ k1 * ... * xn ^ kn`.
|
|||
|
|
fn multi_exponentiate_bounded_exp(
|
|||
|
|
bases_and_exponents: &BasesAndExponents,
|
|||
|
|
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;
|
|||
|
|
}
|