use super::{BoxedMontyForm, BoxedMontyParams};
use crate::{CtOption, Invert, modular::safegcd::boxed::BoxedSafeGcdInverter};
impl BoxedMontyForm {
#[must_use]
pub fn invert(&self) -> CtOption<Self> {
let montgomery_form = self.params.inverter().invert(&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)
}
#[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)
}
}
impl Invert for BoxedMontyForm {
type Output = CtOption<Self>;
fn invert(&self) -> Self::Output {
self.invert()
}
fn invert_vartime(&self) -> Self::Output {
self.invert_vartime()
}
}
impl BoxedMontyParams {
fn inverter(&self) -> BoxedSafeGcdInverter {
BoxedSafeGcdInverter::new_with_inverse(
self.modulus().clone(),
self.mod_inv(),
self.r2().clone(),
)
}
}
#[cfg(test)]
mod tests {
use crate::{
BoxedUint, Invert,
modular::{BoxedMontyForm, BoxedMontyParams},
};
use hex_literal::hex;
fn monty_params() -> BoxedMontyParams {
BoxedMontyParams::new(
BoxedUint::from_be_slice(
&hex!("15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409"),
256,
)
.unwrap()
.to_odd()
.unwrap(),
)
}
#[test]
fn test_self_inverse() {
let params = monty_params();
let x = BoxedUint::from_be_slice(
&hex!("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"),
256,
)
.unwrap();
let x_mod = BoxedMontyForm::new(x, ¶ms);
let inv = x_mod.invert().unwrap();
let res = &x_mod * &inv;
assert!(bool::from(res.retrieve().is_one()));
let inv_trait = Invert::invert(&x_mod).unwrap();
assert_eq!(inv_trait, inv);
}
}