Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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