Skip to content

Commit bc06138

Browse files
authored
Add InvMod trait (#505)
Adds a trait for computing modular inverses with the modulus provided as an argument, impl'd for both `Uint` and `BoxedUint`.
1 parent 84d5495 commit bc06138

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

src/traits.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ pub trait MulMod<Rhs = Self> {
346346
fn mul_mod(&self, rhs: &Rhs, p: &Self) -> Self::Output;
347347
}
348348

349+
/// Compute `1 / self mod p`.
350+
pub trait InvMod: Sized {
351+
/// Compute `1 / self mod p`.
352+
fn inv_mod(&self, p: &Self) -> CtOption<Self>;
353+
}
354+
349355
/// Checked addition.
350356
pub trait CheckedAdd<Rhs = Self>: Sized {
351357
/// Perform checked addition, returning a [`CtOption`] which `is_some` only if the operation

src/uint/boxed/inv_mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! [`BoxedUint`] modular inverse (i.e. reciprocal) operations.
22
33
use crate::{
4-
modular::BoxedBernsteinYangInverter, BoxedUint, ConstantTimeSelect, Integer, Inverter, Odd,
5-
PrecomputeInverter, PrecomputeInverterWithAdjuster,
4+
modular::BoxedBernsteinYangInverter, BoxedUint, ConstantTimeSelect, Integer, InvMod, Inverter,
5+
Odd, PrecomputeInverter, PrecomputeInverterWithAdjuster,
66
};
77
use subtle::{Choice, ConstantTimeEq, ConstantTimeLess, CtOption};
88

@@ -45,6 +45,19 @@ impl BoxedUint {
4545
}
4646
}
4747

48+
impl InvMod for BoxedUint {
49+
/// Note: currently only supports odd modulus
50+
fn inv_mod(&self, modulus: &Self) -> CtOption<Self> {
51+
let modulus = Odd(modulus.clone());
52+
let is_odd = modulus.is_odd();
53+
let maybe_ret = self.inv_odd_mod(&modulus);
54+
let is_some = maybe_ret.is_some() & is_odd;
55+
56+
// use cloned modulus as dummy value for is_none case
57+
CtOption::new(Option::from(maybe_ret).unwrap_or(modulus.get()), is_some)
58+
}
59+
}
60+
4861
/// Precompute a Bernstein-Yang inverter using `self` as the modulus.
4962
impl PrecomputeInverter for Odd<BoxedUint> {
5063
type Inverter = BoxedBernsteinYangInverter;

src/uint/inv_mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use super::Uint;
2-
use crate::modular::BernsteinYangInverter;
3-
use crate::{ConstChoice, ConstCtOption, Odd, PrecomputeInverter};
2+
use crate::{
3+
modular::BernsteinYangInverter, ConstChoice, ConstCtOption, InvMod, Odd, PrecomputeInverter,
4+
};
5+
use subtle::CtOption;
46

57
impl<const LIMBS: usize> Uint<LIMBS> {
68
/// Computes 1/`self` mod `2^k`.
@@ -92,8 +94,8 @@ impl<const LIMBS: usize> Uint<LIMBS> {
9294
}
9395

9496
/// Computes the multiplicative inverse of `self` mod `modulus`.
95-
/// Returns `(inverse, ConstChoice::TRUE)` if an inverse exists,
96-
/// otherwise `(undefined, ConstChoice::FALSE)`.
97+
///
98+
/// Returns some if an inverse exists, otherwise none.
9799
pub const fn inv_mod<const UNSAT_LIMBS: usize>(&self, modulus: &Self) -> ConstCtOption<Self>
98100
where
99101
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<LIMBS, UNSAT_LIMBS>>,
@@ -133,6 +135,15 @@ impl<const LIMBS: usize> Uint<LIMBS> {
133135
}
134136
}
135137

138+
impl<const LIMBS: usize, const UNSAT_LIMBS: usize> InvMod for Uint<LIMBS>
139+
where
140+
Odd<Self>: PrecomputeInverter<Inverter = BernsteinYangInverter<LIMBS, UNSAT_LIMBS>>,
141+
{
142+
fn inv_mod(&self, modulus: &Self) -> CtOption<Self> {
143+
self.inv_mod(modulus).into()
144+
}
145+
}
146+
136147
#[cfg(test)]
137148
mod tests {
138149
use crate::{U1024, U256, U64};

0 commit comments

Comments
 (0)