Skip to content
Open
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
2 changes: 1 addition & 1 deletion benches/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ fn bench_invert_mod(c: &mut Criterion) {
loop {
let x = U256::random_from_rng(&mut rng);
let inv_x = x.invert_odd_mod_vartime(&m);
if inv_x.is_some().into() {
if inv_x.is_some() {
break (x, m);
}
}
Expand Down
29 changes: 16 additions & 13 deletions src/modular/boxed_monty_form/invert.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Multiplicative inverses of boxed integers in Montgomery form.

use super::{BoxedMontyForm, BoxedMontyParams};
use crate::{CtOption, Invert, modular::safegcd::boxed::BoxedSafeGcdInverter};
use crate::{Choice, CtOption, Invert, modular::safegcd::boxed::BoxedSafeGcdInverter};

impl BoxedMontyForm {
/// Computes `self^-1` representing the multiplicative inverse of `self`,
Expand All @@ -22,19 +22,19 @@ impl BoxedMontyForm {
/// Computes `self^-1` representing the multiplicative inverse of `self`,
/// i.e. `self * self^-1 = 1`.
///
/// This version is variable-time with respect to the self of `self`, but constant-time with
/// Returns `None` if the number is not invertible.
///
/// This version is variable-time with respect to the value of `self`, but constant-time with
/// respect to `self`'s `params`.
#[must_use]
pub fn invert_vartime(&self) -> CtOption<Self> {
let montgomery_form = self.params.inverter().invert_vartime(&self.montgomery_form);
let is_some = montgomery_form.is_some();
let montgomery_form2 = self.montgomery_form.clone();
let ret = BoxedMontyForm {
montgomery_form: Option::from(montgomery_form).unwrap_or(montgomery_form2),
params: self.params.clone(),
};

CtOption::new(ret, is_some)
pub fn invert_vartime(&self) -> Option<Self> {
self.params
.inverter()
.invert_vartime(&self.montgomery_form)
.map(|montgomery_form| BoxedMontyForm {
montgomery_form,
params: self.params.clone(),
})
}
}

Expand All @@ -46,7 +46,10 @@ impl Invert for BoxedMontyForm {
}

fn invert_vartime(&self) -> Self::Output {
self.invert_vartime()
match self.invert_vartime() {
Some(value) => CtOption::some(value),
None => CtOption::new(self.clone(), Choice::FALSE),
}
}
}

Expand Down
32 changes: 16 additions & 16 deletions src/modular/const_monty_form/invert.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Multiplicative inverses of integers in Montgomery form with a constant modulus.

use super::{ConstMontyForm, ConstMontyParams};
use crate::{CtOption, Invert, modular::SafeGcdInverter};
use crate::{Choice, CtOption, Invert, modular::SafeGcdInverter};
use core::marker::PhantomData;

impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> ConstMontyForm<MOD, LIMBS> {
Expand Down Expand Up @@ -42,41 +42,38 @@ impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> ConstMontyForm<MOD, LIMBS
/// Computes `self^-1` representing the multiplicative inverse of `self`,
/// i.e. `self * self^-1 = 1`.
///
/// If the number was invertible, the second element of the tuple is the truthy value,
/// otherwise it is the falsy value (in which case the first element's value is unspecified).
/// Returns `None` if the number is not invertible.
///
/// This version is variable-time with respect to the value of `self`, but constant-time with
/// respect to `MOD`.
#[deprecated(since = "0.7.0", note = "please use `invert_vartime` instead")]
#[must_use]
pub const fn inv_vartime(&self) -> CtOption<Self> {
pub const fn inv_vartime(&self) -> Option<Self> {
self.invert_vartime()
}

/// Computes `self^-1` representing the multiplicative inverse of `self`,
/// i.e. `self * self^-1 = 1`.
///
/// If the number was invertible, the second element of the tuple is the truthy value,
/// otherwise it is the falsy value (in which case the first element's value is unspecified).
/// Returns `None` if the number is not invertible.
///
/// This version is variable-time with respect to the value of `self`, but constant-time with
/// respect to `MOD`.
#[must_use]
pub const fn invert_vartime(&self) -> CtOption<Self> {
pub const fn invert_vartime(&self) -> Option<Self> {
let inverter = SafeGcdInverter::new_with_inverse(
&MOD::PARAMS.modulus,
MOD::PARAMS.mod_inv,
&MOD::PARAMS.r2,
);

let maybe_inverse = inverter.invert_vartime(&self.montgomery_form);

let ret = Self {
montgomery_form: maybe_inverse.to_inner_unchecked(),
phantom: PhantomData,
};

CtOption::new(ret, maybe_inverse.is_some())
match inverter.invert_vartime(&self.montgomery_form) {
Some(montgomery_form) => Some(Self {
montgomery_form,
phantom: PhantomData,
}),
None => None,
}
}
}

Expand All @@ -88,7 +85,10 @@ impl<MOD: ConstMontyParams<LIMBS>, const LIMBS: usize> Invert for ConstMontyForm
}

fn invert_vartime(&self) -> Self::Output {
self.invert_vartime()
match self.invert_vartime() {
Some(value) => CtOption::some(value),
None => CtOption::new(*self, Choice::FALSE),
}
}
}

Expand Down
32 changes: 16 additions & 16 deletions src/modular/fixed_monty_form/invert.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Multiplicative inverses of integers in Montgomery form with a modulus set at runtime.

use super::{FixedMontyForm, FixedMontyParams};
use crate::{CtOption, modular::SafeGcdInverter, traits::Invert};
use crate::{Choice, CtOption, modular::SafeGcdInverter, traits::Invert};

impl<const LIMBS: usize> FixedMontyForm<LIMBS> {
/// Computes `self^-1` representing the multiplicative inverse of `self`.
Expand Down Expand Up @@ -36,36 +36,33 @@ impl<const LIMBS: usize> FixedMontyForm<LIMBS> {
/// Computes `self^-1` representing the multiplicative inverse of `self`.
/// i.e. `self * self^-1 = 1`.
///
/// If the number was invertible, the second element of the tuple is the truthy value,
/// otherwise it is the falsy value (in which case the first element's value is unspecified).
/// Returns `None` if the number is not invertible.
///
/// This version is variable-time with respect to the value of `self`, but constant-time with
/// respect to `self`'s `params`.
#[deprecated(since = "0.7.0", note = "please use `invert_vartime` instead")]
#[must_use]
pub const fn inv_vartime(&self) -> CtOption<Self> {
pub const fn inv_vartime(&self) -> Option<Self> {
self.invert_vartime()
}

/// Computes `self^-1` representing the multiplicative inverse of `self`.
/// i.e. `self * self^-1 = 1`.
///
/// If the number was invertible, the second element of the tuple is the truthy value,
/// otherwise it is the falsy value (in which case the first element's value is unspecified).
/// Returns `None` if the number is not invertible.
///
/// This version is variable-time with respect to the value of `self`, but constant-time with
/// respect to `self`'s `params`.
#[must_use]
pub const fn invert_vartime(&self) -> CtOption<Self> {
pub const fn invert_vartime(&self) -> Option<Self> {
let inverter = self.params.inverter();
let maybe_inverse = inverter.invert_vartime(&self.montgomery_form);

let ret = Self {
montgomery_form: maybe_inverse.to_inner_unchecked(),
params: self.params,
};

CtOption::new(ret, maybe_inverse.is_some())
match inverter.invert_vartime(&self.montgomery_form) {
Some(montgomery_form) => Some(Self {
montgomery_form,
params: self.params,
}),
None => None,
}
}
}

Expand All @@ -77,7 +74,10 @@ impl<const LIMBS: usize> Invert for FixedMontyForm<LIMBS> {
}

fn invert_vartime(&self) -> Self::Output {
self.invert_vartime()
match self.invert_vartime() {
Some(value) => CtOption::some(value),
None => CtOption::new(*self, Choice::FALSE),
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/modular/safegcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ impl<const LIMBS: usize> SafeGcdInverter<LIMBS> {
/// depending on invertibility of the argument, i.e. its coprimality with the modulus.
///
/// This version is variable-time with respect to `value`.
pub const fn invert_vartime(&self, value: &Uint<LIMBS>) -> CtOption<Uint<LIMBS>> {
pub const fn invert_vartime(&self, value: &Uint<LIMBS>) -> Option<Uint<LIMBS>> {
invert_odd_mod_precomp::<LIMBS, true>(value, &self.modulus, self.inverse, &self.adjuster)
.into_option_copied()
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/modular/safegcd/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,14 @@ impl BoxedSafeGcdInverter {
}

/// Perform variable-time modular inversion.
pub(crate) fn invert_vartime(&self, value: &BoxedUint) -> CtOption<BoxedUint> {
pub(crate) fn invert_vartime(&self, value: &BoxedUint) -> Option<BoxedUint> {
invert_odd_mod_precomp::<true>(
value,
&self.modulus,
self.inverse,
Some(self.adjuster.clone()),
)
.into_option()
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/uint/boxed/invert_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ impl BoxedUint {
}

/// Computes the multiplicative inverse of `self` mod `modulus`, where `modulus` is odd.
///
/// This method is variable-time with respect to `self`.
#[must_use]
pub fn invert_odd_mod_vartime(&self, modulus: &Odd<Self>) -> CtOption<Self> {
safegcd::boxed::invert_odd_mod::<true>(self, modulus)
pub fn invert_odd_mod_vartime(&self, modulus: &Odd<Self>) -> Option<Self> {
safegcd::boxed::invert_odd_mod::<true>(self, modulus).into_option()
}

/// Computes 1/`self` mod `2^k`.
Expand Down
12 changes: 8 additions & 4 deletions src/uint/boxed/pow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ impl BoxedUint {
CtOption::new(lo, overflow.not())
}

/// Computes `self^exp`, returning a `CtOption` which is none in the case of overflow.
/// Computes `self^exp`, returning `None` in the case of overflow.
///
/// This method is variable time in the exponent `exp` only.
#[must_use]
pub fn checked_pow_vartime(&self, exp: impl AsRef<UintRef>) -> CtOption<Self> {
pub fn checked_pow_vartime(&self, exp: impl AsRef<UintRef>) -> Option<Self> {
let (lo, overflow) = self.overflowing_pow_vartime(exp);
CtOption::new(lo, overflow.not())
if overflow.to_bool_vartime() {
None
} else {
Some(lo)
}
}

/// Computes `self^exp`, returning a `Self::MAX` in the case of overflow.
Expand Down Expand Up @@ -249,7 +253,7 @@ mod tests {
expect.map(BoxedUint::from),
);
assert_eq!(base.checked_pow(&pow).into_option(), expect);
assert_eq!(base.checked_pow_vartime(&pow).into_option(), expect);
assert_eq!(base.checked_pow_vartime(&pow), expect);
assert_eq!(
Checked(CtOption::some(base)).pow(&pow).0.into_option(),
expect
Expand Down
25 changes: 14 additions & 11 deletions src/uint/invert_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,30 +92,33 @@ impl<const LIMBS: usize> Uint<LIMBS> {
/// This method is constant-time w.r.t. `self` but not `k`.
///
/// If the inverse does not exist (`k > 0` and `self` is even),
/// returns `Choice::FALSE` as the second element of the tuple,
/// otherwise returns `Choice::TRUE`.
/// returns `None`, otherwise returns `Some`.
#[deprecated(since = "0.7.0", note = "please use `invert_mod2k_vartime` instead")]
#[must_use]
pub const fn inv_mod2k_vartime(&self, k: u32) -> CtOption<Self> {
pub const fn inv_mod2k_vartime(&self, k: u32) -> Option<Self> {
self.invert_mod2k_vartime(k)
}

/// Computes 1/`self` mod `2^k`.
/// This method is constant-time w.r.t. `self` but not `k`.
///
/// If the inverse does not exist (`k > 0` and `self` is even, or `k > Self::BITS`),
/// returns `CtOption::none`, otherwise returns `CtOption::some`.
/// returns `None`.
#[inline]
#[must_use]
pub const fn invert_mod2k_vartime(&self, k: u32) -> CtOption<Self> {
pub const fn invert_mod2k_vartime(&self, k: u32) -> Option<Self> {
if k == 0 {
CtOption::some(Self::ZERO)
Some(Self::ZERO)
} else if k > Self::BITS {
CtOption::new(Self::ZERO, Choice::FALSE)
None
} else {
let (self_odd, is_some) = self.to_odd_or_one();
let inv = self_odd.invert_mod2k_vartime(k);
CtOption::new(inv, is_some)
if is_some.to_bool_vartime() {
Some(inv)
} else {
None
}
}
}

Expand Down Expand Up @@ -160,8 +163,8 @@ impl<const LIMBS: usize> Uint<LIMBS> {
///
/// This method is variable-time with respect to `self`.
#[must_use]
pub const fn invert_odd_mod_vartime(&self, modulus: &Odd<Self>) -> CtOption<Self> {
safegcd::invert_odd_mod::<LIMBS, true>(self, modulus)
pub const fn invert_odd_mod_vartime(&self, modulus: &Odd<Self>) -> Option<Self> {
safegcd::invert_odd_mod::<LIMBS, true>(self, modulus).into_option_copied()
}

/// Computes the multiplicative inverse of `self` mod `modulus`.
Expand Down Expand Up @@ -306,7 +309,7 @@ mod tests {
assert!(a.is_none().to_bool_vartime());

let a = U256::from(10u64).invert_mod2k_vartime(4);
assert!(a.is_none().to_bool_vartime());
assert!(a.is_none());

// A degenerate case. An inverse mod 2^0 == 1 always exists even for even numbers.

Expand Down
12 changes: 8 additions & 4 deletions src/uint/pow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@ impl<const LIMBS: usize> Uint<LIMBS> {
CtOption::new(lo, overflow.not())
}

/// Computes `self^exp`, returning a `CtOption` which is none in the case of overflow.
/// Computes `self^exp`, returning `None` in the case of overflow.
///
/// This method is variable time in the exponent `exp` only.
#[must_use]
pub const fn checked_pow_vartime<const RHS_LIMBS: usize>(
&self,
exp: &Uint<RHS_LIMBS>,
) -> CtOption<Self> {
) -> Option<Self> {
let (lo, overflow) = self.overflowing_pow_vartime(exp);
CtOption::new(lo, overflow.not())
if overflow.to_bool_vartime() {
None
} else {
Some(lo)
}
}

/// Computes `self^exp`, returning a `Self::MAX` in the case of overflow.
Expand Down Expand Up @@ -252,7 +256,7 @@ mod tests {
];
for (base, pow, expect) in checks {
assert_eq!(base.checked_pow(&pow).into_option(), expect);
assert_eq!(base.checked_pow_vartime(&pow).into_option(), expect);
assert_eq!(base.checked_pow_vartime(&pow), expect);
assert_eq!(
Checked(CtOption::some(base)).pow(&pow).0.into_option(),
expect
Expand Down
2 changes: 1 addition & 1 deletion src/uint/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ mod tests {
.expect("overflow, {s} exp={exp}, root={rt}");
assert!(s2 <= s.get(), "overflow, {s} exp={exp}, root={root}");
let rt_p1 = root.wrapping_add_limb(Limb::ONE);
let s3 = rt_p1.checked_pow_vartime(&exp_uint).into_option();
let s3 = rt_p1.checked_pow_vartime(&exp_uint);
assert!(
s3.is_none_or(|s3| s3 > s2),
"underflow, {s} exp={exp}, root={root}"
Expand Down