Skip to content

Commit

Permalink
Add InvMod trait (#505)
Browse files Browse the repository at this point in the history
Adds a trait for computing modular inverses with the modulus provided
as an argument, impl'd for both `Uint` and `BoxedUint`.
  • Loading branch information
tarcieri authored Dec 23, 2023
1 parent 84d5495 commit bc06138
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ pub trait MulMod<Rhs = Self> {
fn mul_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
}

/// Compute `1 / self mod p`.
pub trait InvMod: Sized {
/// Compute `1 / self mod p`.
fn inv_mod(&self, p: &Self) -> CtOption<Self>;
}

/// Checked addition.
pub trait CheckedAdd<Rhs = Self>: Sized {
/// Perform checked addition, returning a [`CtOption`] which `is_some` only if the operation
Expand Down
17 changes: 15 additions & 2 deletions src/uint/boxed/inv_mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! [`BoxedUint`] modular inverse (i.e. reciprocal) operations.
use crate::{
modular::BoxedBernsteinYangInverter, BoxedUint, ConstantTimeSelect, Integer, Inverter, Odd,
PrecomputeInverter, PrecomputeInverterWithAdjuster,
modular::BoxedBernsteinYangInverter, BoxedUint, ConstantTimeSelect, Integer, InvMod, Inverter,
Odd, PrecomputeInverter, PrecomputeInverterWithAdjuster,
};
use subtle::{Choice, ConstantTimeEq, ConstantTimeLess, CtOption};

Expand Down Expand Up @@ -45,6 +45,19 @@ impl BoxedUint {
}
}

impl InvMod for BoxedUint {
/// Note: currently only supports odd modulus
fn inv_mod(&self, modulus: &Self) -> CtOption<Self> {
let modulus = Odd(modulus.clone());
let is_odd = modulus.is_odd();
let maybe_ret = self.inv_odd_mod(&modulus);
let is_some = maybe_ret.is_some() & is_odd;

// use cloned modulus as dummy value for is_none case
CtOption::new(Option::from(maybe_ret).unwrap_or(modulus.get()), is_some)
}
}

/// Precompute a Bernstein-Yang inverter using `self` as the modulus.
impl PrecomputeInverter for Odd<BoxedUint> {
type Inverter = BoxedBernsteinYangInverter;
Expand Down
19 changes: 15 additions & 4 deletions src/uint/inv_mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::Uint;
use crate::modular::BernsteinYangInverter;
use crate::{ConstChoice, ConstCtOption, Odd, PrecomputeInverter};
use crate::{
modular::BernsteinYangInverter, ConstChoice, ConstCtOption, InvMod, Odd, PrecomputeInverter,
};
use subtle::CtOption;

impl<const LIMBS: usize> Uint<LIMBS> {
/// Computes 1/`self` mod `2^k`.
Expand Down Expand Up @@ -92,8 +94,8 @@ impl<const LIMBS: usize> Uint<LIMBS> {
}

/// Computes the multiplicative inverse of `self` mod `modulus`.
/// Returns `(inverse, ConstChoice::TRUE)` if an inverse exists,
/// otherwise `(undefined, ConstChoice::FALSE)`.
///
/// Returns some if an inverse exists, otherwise none.
pub const fn inv_mod<const UNSAT_LIMBS: usize>(&self, modulus: &Self) -> ConstCtOption<Self>
where
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<LIMBS, UNSAT_LIMBS>>,
Expand Down Expand Up @@ -133,6 +135,15 @@ impl<const LIMBS: usize> Uint<LIMBS> {
}
}

impl<const LIMBS: usize, const UNSAT_LIMBS: usize> InvMod for Uint<LIMBS>
where
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<LIMBS, UNSAT_LIMBS>>,
{
fn inv_mod(&self, modulus: &Self) -> CtOption<Self> {
self.inv_mod(modulus).into()
}
}

#[cfg(test)]
mod tests {
use crate::{U1024, U256, U64};
Expand Down

0 comments on commit bc06138

Please sign in to comment.