diff --git a/Cargo.toml b/Cargo.toml index e99c5b175..a56bc6f2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [[bench]] -name = "boxed_residue" +name = "boxed_monty" harness = false required-features = ["alloc"] @@ -62,7 +62,7 @@ harness = false required-features = ["alloc"] [[bench]] -name = "dyn_residue" +name = "const_monty" harness = false [[bench]] @@ -70,7 +70,7 @@ name = "limb" harness = false [[bench]] -name = "residue" +name = "monty" harness = false [[bench]] diff --git a/benches/boxed_residue.rs b/benches/boxed_monty.rs similarity index 77% rename from benches/boxed_residue.rs rename to benches/boxed_monty.rs index 9650df485..c2c75e5d1 100644 --- a/benches/boxed_residue.rs +++ b/benches/boxed_monty.rs @@ -3,7 +3,7 @@ use criterion::{ BenchmarkGroup, Criterion, }; use crypto_bigint::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, NonZero, RandomMod, }; use num_bigint::BigUint; @@ -17,7 +17,7 @@ fn to_biguint(uint: &BoxedUint) -> BigUint { } fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { - let params = BoxedResidueParams::new( + let params = BoxedMontyParams::new( BoxedUint::random(&mut OsRng, UINT_BITS) | BoxedUint::one_with_precision(UINT_BITS), ) .unwrap(); @@ -26,7 +26,7 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { b.iter_batched( || { let modulus = NonZero::new(params.modulus().clone()).unwrap(); - BoxedResidue::new(BoxedUint::random_mod(&mut OsRng, &modulus), params.clone()) + BoxedMontyForm::new(BoxedUint::random_mod(&mut OsRng, &modulus), params.clone()) }, |x| black_box(x).invert(), BatchSize::SmallInput, @@ -36,8 +36,10 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { group.bench_function("multiplication, BoxedUint*BoxedUint", |b| { b.iter_batched( || { - let x = BoxedResidue::new(BoxedUint::random(&mut OsRng, UINT_BITS), params.clone()); - let y = BoxedResidue::new(BoxedUint::random(&mut OsRng, UINT_BITS), params.clone()); + let x = + BoxedMontyForm::new(BoxedUint::random(&mut OsRng, UINT_BITS), params.clone()); + let y = + BoxedMontyForm::new(BoxedUint::random(&mut OsRng, UINT_BITS), params.clone()); (x, y) }, |(x, y)| black_box(x * y), @@ -59,12 +61,12 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { }); let m = BoxedUint::random(&mut OsRng, UINT_BITS) | BoxedUint::one_with_precision(UINT_BITS); - let params = BoxedResidueParams::new(m).unwrap(); + let params = BoxedMontyParams::new(m).unwrap(); group.bench_function("modpow, BoxedUint^BoxedUint", |b| { b.iter_batched( || { let x = BoxedUint::random(&mut OsRng, UINT_BITS); - let x_m = BoxedResidue::new(x, params.clone()); + let x_m = BoxedMontyForm::new(x, params.clone()); let p = BoxedUint::random(&mut OsRng, UINT_BITS) | (BoxedUint::one_with_precision(UINT_BITS) << (UINT_BITS - 1)); (x_m, p) @@ -92,41 +94,41 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { } fn bench_montgomery_conversion(group: &mut BenchmarkGroup<'_, M>) { - group.bench_function("BoxedResidueParams::new", |b| { + group.bench_function("BoxedMontyParams::new", |b| { b.iter_batched( || BoxedUint::random(&mut OsRng, UINT_BITS) | BoxedUint::one_with_precision(UINT_BITS), - |modulus| black_box(BoxedResidueParams::new(modulus)), + |modulus| black_box(BoxedMontyParams::new(modulus)), BatchSize::SmallInput, ) }); - group.bench_function("BoxedResidueParams::new_vartime", |b| { + group.bench_function("BoxedMontyParams::new_vartime", |b| { b.iter_batched( || BoxedUint::random(&mut OsRng, UINT_BITS) | BoxedUint::one_with_precision(UINT_BITS), - |modulus| black_box(BoxedResidueParams::new_vartime(modulus)), + |modulus| black_box(BoxedMontyParams::new_vartime(modulus)), BatchSize::SmallInput, ) }); - let params = BoxedResidueParams::new( + let params = BoxedMontyParams::new( BoxedUint::random(&mut OsRng, UINT_BITS) | BoxedUint::one_with_precision(UINT_BITS), ) .unwrap(); - group.bench_function("BoxedResidue::new", |b| { + group.bench_function("BoxedMontyForm::new", |b| { b.iter_batched( || BoxedUint::random(&mut OsRng, UINT_BITS), - |x| black_box(BoxedResidue::new(x, params.clone())), + |x| black_box(BoxedMontyForm::new(x, params.clone())), BatchSize::SmallInput, ) }); - let params = BoxedResidueParams::new( + let params = BoxedMontyParams::new( BoxedUint::random(&mut OsRng, UINT_BITS) | BoxedUint::one_with_precision(UINT_BITS), ) .unwrap(); - group.bench_function("BoxedResidue::retrieve", |b| { + group.bench_function("BoxedMontyForm::retrieve", |b| { b.iter_batched( - || BoxedResidue::new(BoxedUint::random(&mut OsRng, UINT_BITS), params.clone()), + || BoxedMontyForm::new(BoxedUint::random(&mut OsRng, UINT_BITS), params.clone()), |x| black_box(x.retrieve()), BatchSize::SmallInput, ) diff --git a/benches/residue.rs b/benches/const_monty.rs similarity index 73% rename from benches/residue.rs rename to benches/const_monty.rs index 2a5e28336..380fd273c 100644 --- a/benches/residue.rs +++ b/benches/const_monty.rs @@ -2,7 +2,7 @@ use criterion::{ black_box, criterion_group, criterion_main, measurement::Measurement, BatchSize, BenchmarkGroup, Criterion, }; -use crypto_bigint::{impl_modulus, modular::ResidueParams, Invert, Inverter, Random, U256}; +use crypto_bigint::{impl_modulus, modular::ConstMontyParams, Invert, Inverter, Random, U256}; use rand_core::OsRng; #[cfg(feature = "alloc")] @@ -14,20 +14,20 @@ impl_modulus!( "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" ); -type Residue = crypto_bigint::modular::Residue; +type ConstMontyForm = crypto_bigint::modular::ConstMontyForm; fn bench_montgomery_conversion(group: &mut BenchmarkGroup<'_, M>) { - group.bench_function("Residue creation", |b| { + group.bench_function("ConstMontyForm creation", |b| { b.iter_batched( || U256::random(&mut OsRng), - |x| black_box(Residue::new(&x)), + |x| black_box(ConstMontyForm::new(&x)), BatchSize::SmallInput, ) }); - group.bench_function("Residue retrieve", |b| { + group.bench_function("ConstMontyForm retrieve", |b| { b.iter_batched( - || Residue::new(&U256::random(&mut OsRng)), + || ConstMontyForm::new(&U256::random(&mut OsRng)), |x| black_box(x.retrieve()), BatchSize::SmallInput, ) @@ -37,7 +37,7 @@ fn bench_montgomery_conversion(group: &mut BenchmarkGroup<'_, M> fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { group.bench_function("invert, U256", |b| { b.iter_batched( - || Residue::new(&U256::random(&mut OsRng)), + || ConstMontyForm::new(&U256::random(&mut OsRng)), |x| black_box(x).invert(), BatchSize::SmallInput, ) @@ -46,7 +46,7 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { group.bench_function("Bernstein-Yang invert, U256", |b| { b.iter_batched( || { - let x = Residue::new(&U256::random(&mut OsRng)); + let x = ConstMontyForm::new(&U256::random(&mut OsRng)); let inverter = Modulus::precompute_inverter(); (x, inverter) }, @@ -58,8 +58,8 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { group.bench_function("multiplication, U256*U256", |b| { b.iter_batched( || { - let x = Residue::new(&U256::random(&mut OsRng)); - let y = Residue::new(&U256::random(&mut OsRng)); + let x = ConstMontyForm::new(&U256::random(&mut OsRng)); + let y = ConstMontyForm::new(&U256::random(&mut OsRng)); (x, y) }, |(x, y)| black_box(x * y), @@ -71,7 +71,7 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { b.iter_batched( || { let x = U256::random(&mut OsRng); - let x_m = Residue::new(&x); + let x_m = ConstMontyForm::new(&x); let p = U256::random(&mut OsRng) | (U256::ONE << (U256::BITS - 1)); (x_m, p) }, @@ -87,10 +87,10 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { |b| { b.iter_batched( || { - let bases_and_exponents: Vec<(Residue, U256)> = (1..=i) + let bases_and_exponents: Vec<(ConstMontyForm, U256)> = (1..=i) .map(|_| { let x = U256::random(&mut OsRng); - let x_m = Residue::new(&x); + let x_m = ConstMontyForm::new(&x); let p = U256::random(&mut OsRng) | (U256::ONE << (U256::BITS - 1)); (x_m, p) }) @@ -99,7 +99,9 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { bases_and_exponents }, |bases_and_exponents| { - black_box(Residue::multi_exponentiate(bases_and_exponents.as_slice())) + black_box(ConstMontyForm::multi_exponentiate( + bases_and_exponents.as_slice(), + )) }, BatchSize::SmallInput, ) diff --git a/benches/dyn_residue.rs b/benches/monty.rs similarity index 70% rename from benches/dyn_residue.rs rename to benches/monty.rs index a7f2b2119..57c63f491 100644 --- a/benches/dyn_residue.rs +++ b/benches/monty.rs @@ -3,7 +3,7 @@ use criterion::{ BenchmarkGroup, Criterion, }; use crypto_bigint::{ - modular::{DynResidue, DynResidueParams}, + modular::{MontyForm, MontyParams}, Invert, Inverter, PrecomputeInverter, Random, U256, }; use rand_core::OsRng; @@ -12,27 +12,27 @@ use rand_core::OsRng; use crypto_bigint::MultiExponentiate; fn bench_montgomery_conversion(group: &mut BenchmarkGroup<'_, M>) { - group.bench_function("DynResidueParams creation", |b| { + group.bench_function("MontyParams creation", |b| { b.iter_batched( || U256::random(&mut OsRng) | U256::ONE, - |modulus| black_box(DynResidueParams::new(&modulus)), + |modulus| black_box(MontyParams::new(&modulus)), BatchSize::SmallInput, ) }); - let params = DynResidueParams::new(&(U256::random(&mut OsRng) | U256::ONE)).unwrap(); - group.bench_function("DynResidue creation", |b| { + let params = MontyParams::new(&(U256::random(&mut OsRng) | U256::ONE)).unwrap(); + group.bench_function("MontyForm creation", |b| { b.iter_batched( || U256::random(&mut OsRng), - |x| black_box(DynResidue::new(&x, params)), + |x| black_box(MontyForm::new(&x, params)), BatchSize::SmallInput, ) }); - let params = DynResidueParams::new(&(U256::random(&mut OsRng) | U256::ONE)).unwrap(); - group.bench_function("DynResidue retrieve", |b| { + let params = MontyParams::new(&(U256::random(&mut OsRng) | U256::ONE)).unwrap(); + group.bench_function("MontyForm retrieve", |b| { b.iter_batched( - || DynResidue::new(&U256::random(&mut OsRng), params), + || MontyForm::new(&U256::random(&mut OsRng), params), |x| black_box(x.retrieve()), BatchSize::SmallInput, ) @@ -40,11 +40,11 @@ fn bench_montgomery_conversion(group: &mut BenchmarkGroup<'_, M> } fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { - let params = DynResidueParams::new(&(U256::random(&mut OsRng) | U256::ONE)).unwrap(); + let params = MontyParams::new(&(U256::random(&mut OsRng) | U256::ONE)).unwrap(); group.bench_function("invert, U256", |b| { b.iter_batched( - || DynResidue::new(&U256::random(&mut OsRng), params), + || MontyForm::new(&U256::random(&mut OsRng), params), |x| black_box(x).invert(), BatchSize::SmallInput, ) @@ -53,7 +53,7 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { group.bench_function("Bernstein-Yang invert, U256", |b| { b.iter_batched( || { - let x = DynResidue::new(&U256::random(&mut OsRng), params); + let x = MontyForm::new(&U256::random(&mut OsRng), params); let inverter = x.params().precompute_inverter(); (x, inverter) }, @@ -65,8 +65,8 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { group.bench_function("multiplication, U256*U256", |b| { b.iter_batched( || { - let x = DynResidue::new(&U256::random(&mut OsRng), params); - let y = DynResidue::new(&U256::random(&mut OsRng), params); + let x = MontyForm::new(&U256::random(&mut OsRng), params); + let y = MontyForm::new(&U256::random(&mut OsRng), params); (x, y) }, |(x, y)| black_box(x * y), @@ -78,7 +78,7 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { b.iter_batched( || { let x = U256::random(&mut OsRng); - let x_m = DynResidue::new(&x, params); + let x_m = MontyForm::new(&x, params); let p = U256::random(&mut OsRng) | (U256::ONE << (U256::BITS - 1)); (x_m, p) }, @@ -94,10 +94,10 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { |b| { b.iter_batched( || { - let bases_and_exponents: Vec<(DynResidue<{ U256::LIMBS }>, U256)> = (1..=i) + let bases_and_exponents: Vec<(MontyForm<{ U256::LIMBS }>, U256)> = (1..=i) .map(|_| { let x = U256::random(&mut OsRng); - let x_m = DynResidue::new(&x, params); + let x_m = MontyForm::new(&x, params); let p = U256::random(&mut OsRng) | (U256::ONE << (U256::BITS - 1)); (x_m, p) }) @@ -106,7 +106,7 @@ fn bench_montgomery_ops(group: &mut BenchmarkGroup<'_, M>) { bases_and_exponents }, |bases_and_exponents| { - black_box(DynResidue::<{ U256::LIMBS }>::multi_exponentiate( + black_box(MontyForm::<{ U256::LIMBS }>::multi_exponentiate( bases_and_exponents.as_slice(), )) }, diff --git a/src/lib.rs b/src/lib.rs index 735db7aea..ab9240708 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -110,8 +110,8 @@ //! assert_eq!(b, U256::ZERO); //! ``` //! -//! It also supports modular arithmetic over constant moduli using `Residue`, -//! and over moduli set at runtime using `DynResidue`. +//! It also supports modular arithmetic over constant moduli using `ConstMontyForm`, +//! and over moduli set at runtime using `MontyForm`. //! That includes modular exponentiation and multiplicative inverses. //! These features are described in the [`modular`] module. //! diff --git a/src/modular.rs b/src/modular.rs index 32e81bd7e..8e0dc4c1c 100644 --- a/src/modular.rs +++ b/src/modular.rs @@ -5,20 +5,20 @@ //! //! # Constant moduli //! -//! The [`Residue`] and [`ResidueParams`] types implement support for modular arithmetic where the +//! The [`ConstMontyForm`] and [`ConstMontyParams`] types implement support for modular arithmetic where the //! modulus is fixed at compile-time. //! //! The [`impl_modulus!`][`crate::impl_modulus`] macro can be used to define a compile-time modulus, -//! whereas the [`const_residue!`][`crate::const_residue`] macro can define a [`Residue`] constant. +//! whereas the [`const_monty_form!`][`crate::const_monty_form`] macro can define a [`ConstMontyForm`] constant. //! //! # Dynamic moduli chosen at runtime //! -//! The [`DynResidue`] and [`DynResidueParams`] types implement support for modular arithmetic where +//! The [`MontyForm`] and [`MontyParams`] types implement support for modular arithmetic where //! the modulus can vary at runtime. -mod dyn_residue; +mod const_monty_form; +mod monty_form; mod reduction; -mod residue; mod add; mod bernstein_yang; @@ -28,17 +28,17 @@ mod pow; mod sub; #[cfg(feature = "alloc")] -pub(crate) mod boxed_residue; +pub(crate) mod boxed_monty_form; pub use self::{ bernstein_yang::BernsteinYangInverter, - dyn_residue::{inv::DynResidueInverter, DynResidue, DynResidueParams}, + const_monty_form::{inv::ConstMontyFormInverter, ConstMontyForm, ConstMontyParams}, + monty_form::{inv::MontyFormInverter, MontyForm, MontyParams}, reduction::montgomery_reduction, - residue::{inv::ResidueInverter, Residue, ResidueParams}, }; #[cfg(feature = "alloc")] -pub use self::boxed_residue::{BoxedResidue, BoxedResidueParams}; +pub use self::boxed_monty_form::{BoxedMontyForm, BoxedMontyParams}; /// A generalization for numbers kept in optimized representations (e.g. Montgomery) /// that can be converted back to the original form. @@ -53,10 +53,10 @@ pub trait Retrieve { #[cfg(test)] mod tests { use crate::{ - const_residue, impl_modulus, + const_monty_form, impl_modulus, modular::{ + const_monty_form::{ConstMontyForm, ConstMontyParams}, reduction::montgomery_reduction, - residue::{Residue, ResidueParams}, }, NonZero, Uint, U256, U64, }; @@ -70,7 +70,7 @@ mod tests { #[test] fn test_montgomery_params() { assert_eq!( - Modulus1::R, + Modulus1::ONE, U256::from_be_hex("1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffe") ); assert_eq!( @@ -90,11 +90,11 @@ mod tests { ); #[test] - fn test_reducing_r() { + fn test_reducing_one() { // Divide the value R by R, which should equal 1 assert_eq!( montgomery_reduction::<{ Modulus2::LIMBS }>( - &(Modulus2::R, Uint::ZERO), + &(Modulus2::ONE, Uint::ZERO), &Modulus2::MODULUS, Modulus2::MOD_NEG_INV ), @@ -111,21 +111,21 @@ mod tests { &Modulus2::MODULUS, Modulus2::MOD_NEG_INV ), - Modulus2::R + Modulus2::ONE ); } #[test] fn test_reducing_r2_wide() { - // Divide the value R^2 by R, which should equal R - let (hi, lo) = Modulus2::R.square().split(); + // Divide the value ONE^2 by R, which should equal ONE + let (hi, lo) = Modulus2::ONE.square().split(); assert_eq!( montgomery_reduction::<{ Modulus2::LIMBS }>( &(lo, hi), &Modulus2::MODULUS, Modulus2::MOD_NEG_INV ), - Modulus2::R + Modulus2::ONE ); } @@ -134,7 +134,7 @@ mod tests { // Reducing xR should return x let x = U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); - let product = x.split_mul(&Modulus2::R); + let product = x.split_mul(&Modulus2::ONE); assert_eq!( montgomery_reduction::<{ Modulus2::LIMBS }>( &product, @@ -153,7 +153,7 @@ mod tests { let product = x.split_mul(&Modulus2::R2); // Computing xR mod modulus without Montgomery reduction - let (lo, hi) = x.split_mul(&Modulus2::R); + let (lo, hi) = x.split_mul(&Modulus2::ONE); let c = hi.concat(&lo); let red = c.rem_vartime(&NonZero::new(U256::ZERO.concat(&Modulus2::MODULUS)).unwrap()); let (hi, lo) = red.split(); @@ -173,19 +173,19 @@ mod tests { fn test_new_retrieve() { let x = U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); - let x_mod = Residue::::new(&x); + let x_mod = ConstMontyForm::::new(&x); // Confirm that when creating a Modular and retrieving the value, that it equals the original assert_eq!(x, x_mod.retrieve()); } #[test] - fn test_residue_macro() { + fn test_const_monty_form_macro() { let x = U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); assert_eq!( - Residue::::new(&x), - const_residue!(x, Modulus2) + ConstMontyForm::::new(&x), + const_monty_form!(x, Modulus2) ); } } diff --git a/src/modular/boxed_residue.rs b/src/modular/boxed_monty_form.rs similarity index 56% rename from src/modular/boxed_residue.rs rename to src/modular/boxed_monty_form.rs index d9e0a120b..c2b3f2a16 100644 --- a/src/modular/boxed_residue.rs +++ b/src/modular/boxed_monty_form.rs @@ -1,4 +1,4 @@ -//! Implements `BoxedResidue`s, supporting modular arithmetic with a modulus whose size and value +//! Implements `BoxedMontyForm`s, supporting modular arithmetic with a modulus whose size and value //! is chosen at runtime. mod add; @@ -24,11 +24,11 @@ use zeroize::Zeroize; /// Parameters to efficiently go to/from the Montgomery form for an odd modulus whose size and value /// are both chosen at runtime. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct BoxedResidueParams { +pub struct BoxedMontyParams { /// The constant modulus modulus: BoxedUint, /// Parameter used in Montgomery reduction - r: BoxedUint, + one: BoxedUint, /// R^2, used to move into Montgomery form r2: BoxedUint, /// R^3, used to compute the multiplicative inverse @@ -38,12 +38,12 @@ pub struct BoxedResidueParams { mod_neg_inv: Limb, } -impl BoxedResidueParams { - /// Instantiates a new set of [`BoxedResidueParams`] representing the given `modulus`, which +impl BoxedMontyParams { + /// Instantiates a new set of [`BoxedMontyParams`] representing the given `modulus`, which /// must be odd. /// /// Returns a `CtOption` that is `None` if the provided modulus is not odd. - /// TODO(tarcieri): DRY out with `DynResidueParams::new`? + /// TODO(tarcieri): DRY out with `MontyParams::new`? pub fn new(modulus: BoxedUint) -> CtOption { let bits_precision = modulus.bits_precision(); @@ -56,23 +56,26 @@ impl BoxedResidueParams { )) .expect("modulus ensured non-zero"); - let r = BoxedUint::max(bits_precision) + // `R mod modulus` where `R = 2^BITS`. + // Represents 1 in Montgomery form. + let one = BoxedUint::max(bits_precision) .rem(&modulus_nz) .wrapping_add(&BoxedUint::one()); - let r2 = r + // `R^2 mod modulus`, used to convert integers to Montgomery form. + let r2 = one .square() .rem(&modulus_nz.widen(bits_precision * 2)) .shorten(bits_precision); - Self::new_inner(modulus, r, r2) + Self::new_inner(modulus, one, r2) } - /// Instantiates a new set of [`BoxedResidueParams`] representing the given `modulus`, which + /// Instantiates a new set of [`BoxedMontyParams`] representing the given `modulus`, which /// must be odd. This version operates in variable-time with respect to the modulus. /// /// Returns `None` if the provided modulus is not odd. - /// TODO(tarcieri): DRY out with `DynResidueParams::new`? + /// TODO(tarcieri): DRY out with `MontyParams::new`? pub fn new_vartime(modulus: BoxedUint) -> Option { if modulus.is_even().into() { return None; @@ -89,21 +92,24 @@ impl BoxedResidueParams { )) .expect("modulus ensured non-zero"); - let r = BoxedUint::max(bits_precision) + // `R mod modulus` where `R = 2^BITS`. + // Represents 1 in Montgomery form. + let one = BoxedUint::max(bits_precision) .rem_vartime(&modulus_nz) .wrapping_add(&BoxedUint::one()); - let r2 = r + // `R^2 mod modulus`, used to convert integers to Montgomery form. + let r2 = one .square() .rem_vartime(&modulus_nz.widen(bits_precision * 2)) .shorten(bits_precision); - Self::new_inner(modulus, r, r2).into() + Self::new_inner(modulus, one, r2).into() } /// Common functionality of `new` and `new_vartime`. - fn new_inner(modulus: BoxedUint, r: BoxedUint, r2: BoxedUint) -> CtOption { - debug_assert_eq!(r.bits_precision(), modulus.bits_precision()); + fn new_inner(modulus: BoxedUint, one: BoxedUint, r2: BoxedUint) -> CtOption { + debug_assert_eq!(one.bits_precision(), modulus.bits_precision()); debug_assert_eq!(r2.bits_precision(), modulus.bits_precision()); // If the inverse exists, it means the modulus is odd. @@ -113,7 +119,7 @@ impl BoxedResidueParams { let params = Self { modulus, - r, + one, r2, r3, mod_neg_inv, @@ -133,112 +139,112 @@ impl BoxedResidueParams { } } -/// A residue represented using heap-allocated limbs. +/// An integer in Montgomery form represented using heap-allocated limbs. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct BoxedResidue { - /// Value in the Montgomery domain. +pub struct BoxedMontyForm { + /// Value in the Montgomery form. montgomery_form: BoxedUint, - /// Residue parameters. + /// Montgomery form parameters. #[cfg(not(feature = "std"))] - residue_params: BoxedResidueParams, + params: BoxedMontyParams, - /// Residue parameters. + /// Montgomery form parameters. // Uses `Arc` when `std` is available. #[cfg(feature = "std")] - residue_params: Arc, + params: Arc, } -impl BoxedResidue { - /// Instantiates a new [`BoxedResidue`] that represents an integer modulo the provided params. - pub fn new(mut integer: BoxedUint, residue_params: BoxedResidueParams) -> Self { - debug_assert_eq!(integer.bits_precision(), residue_params.bits_precision()); - convert_to_montgomery(&mut integer, &residue_params); +impl BoxedMontyForm { + /// Instantiates a new [`BoxedMontyForm`] that represents an integer modulo the provided params. + pub fn new(mut integer: BoxedUint, params: BoxedMontyParams) -> Self { + debug_assert_eq!(integer.bits_precision(), params.bits_precision()); + convert_to_montgomery(&mut integer, ¶ms); #[allow(clippy::useless_conversion)] Self { montgomery_form: integer, - residue_params: residue_params.into(), + params: params.into(), } } - /// Instantiates a new [`BoxedResidue`] that represents an integer modulo the provided params. + /// Instantiates a new [`BoxedMontyForm`] that represents an integer modulo the provided params. #[cfg(feature = "std")] - pub fn new_with_arc(mut integer: BoxedUint, residue_params: Arc) -> Self { - debug_assert_eq!(integer.bits_precision(), residue_params.bits_precision()); - convert_to_montgomery(&mut integer, &residue_params); + pub fn new_with_arc(mut integer: BoxedUint, params: Arc) -> Self { + debug_assert_eq!(integer.bits_precision(), params.bits_precision()); + convert_to_montgomery(&mut integer, ¶ms); Self { montgomery_form: integer, - residue_params, + params, } } /// Bits of precision in the modulus. pub fn bits_precision(&self) -> u32 { - self.residue_params.bits_precision() + self.params.bits_precision() } - /// Retrieves the integer currently encoded in this [`BoxedResidue`], guaranteed to be reduced. + /// Retrieves the integer currently encoded in this [`BoxedMontyForm`], guaranteed to be reduced. pub fn retrieve(&self) -> BoxedUint { let mut montgomery_form = self.montgomery_form.widen(self.bits_precision() * 2); let ret = montgomery_reduction_boxed( &mut montgomery_form, - &self.residue_params.modulus, - self.residue_params.mod_neg_inv, + &self.params.modulus, + self.params.mod_neg_inv, ); #[cfg(feature = "zeroize")] montgomery_form.zeroize(); - debug_assert!(ret < self.residue_params.modulus); + debug_assert!(ret < self.params.modulus); ret } - /// Instantiates a new `Residue` that represents zero. - pub fn zero(residue_params: BoxedResidueParams) -> Self { + /// Instantiates a new `ConstMontyForm` that represents zero. + pub fn zero(params: BoxedMontyParams) -> Self { Self { - montgomery_form: BoxedUint::zero_with_precision(residue_params.bits_precision()), - residue_params: residue_params.into(), + montgomery_form: BoxedUint::zero_with_precision(params.bits_precision()), + params: params.into(), } } - /// Instantiates a new `Residue` that represents 1. - pub fn one(residue_params: BoxedResidueParams) -> Self { + /// Instantiates a new `ConstMontyForm` that represents 1. + pub fn one(params: BoxedMontyParams) -> Self { Self { - montgomery_form: residue_params.r.clone(), - residue_params: residue_params.into(), + montgomery_form: params.one.clone(), + params: params.into(), } } - /// Returns the parameter struct used to initialize this residue. - pub fn params(&self) -> &BoxedResidueParams { - &self.residue_params + /// Returns the parameter struct used to initialize this object. + pub fn params(&self) -> &BoxedMontyParams { + &self.params } - /// Access the [`BoxedResidue`] value in Montgomery form. + /// Access the [`BoxedMontyForm`] value in Montgomery form. pub fn as_montgomery(&self) -> &BoxedUint { - debug_assert!(self.montgomery_form < self.residue_params.modulus); + debug_assert!(self.montgomery_form < self.params.modulus); &self.montgomery_form } - /// Create a [`BoxedResidue`] from a value in Montgomery form. - pub fn from_montgomery(integer: BoxedUint, residue_params: BoxedResidueParams) -> Self { - debug_assert_eq!(integer.bits_precision(), residue_params.bits_precision()); + /// Create a [`BoxedMontyForm`] from a value in Montgomery form. + pub fn from_montgomery(integer: BoxedUint, params: BoxedMontyParams) -> Self { + debug_assert_eq!(integer.bits_precision(), params.bits_precision()); Self { montgomery_form: integer, - residue_params: residue_params.into(), + params: params.into(), } } - /// Extract the value from the [`BoxedResidue`] in Montgomery form. + /// Extract the value from the [`BoxedMontyForm`] in Montgomery form. pub fn to_montgomery(&self) -> BoxedUint { - debug_assert!(self.montgomery_form < self.residue_params.modulus); + debug_assert!(self.montgomery_form < self.params.modulus); self.montgomery_form.clone() } } -impl Retrieve for BoxedResidue { +impl Retrieve for BoxedMontyForm { type Output = BoxedUint; fn retrieve(&self) -> BoxedUint { self.retrieve() @@ -247,14 +253,9 @@ impl Retrieve for BoxedResidue { /// Convert the given integer into the Montgomery domain. #[inline] -fn convert_to_montgomery(integer: &mut BoxedUint, residue_params: &BoxedResidueParams) { - let mut product = integer.mul(&residue_params.r2); - montgomery_reduction_boxed_mut( - &mut product, - &residue_params.modulus, - residue_params.mod_neg_inv, - integer, - ); +fn convert_to_montgomery(integer: &mut BoxedUint, params: &BoxedMontyParams) { + let mut product = integer.mul(¶ms.r2); + montgomery_reduction_boxed_mut(&mut product, ¶ms.modulus, params.mod_neg_inv, integer); #[cfg(feature = "zeroize")] product.zeroize(); @@ -262,21 +263,21 @@ fn convert_to_montgomery(integer: &mut BoxedUint, residue_params: &BoxedResidueP #[cfg(test)] mod tests { - use super::{BoxedResidueParams, BoxedUint}; + use super::{BoxedMontyParams, BoxedUint}; #[test] fn new_params_with_invalid_modulus() { // 0 - let ret = BoxedResidueParams::new(BoxedUint::zero()); + let ret = BoxedMontyParams::new(BoxedUint::zero()); assert!(bool::from(ret.is_none())); // 2 - let ret = BoxedResidueParams::new(BoxedUint::from(2u8)); + let ret = BoxedMontyParams::new(BoxedUint::from(2u8)); assert!(bool::from(ret.is_none())); } #[test] fn new_params_with_valid_modulus() { - BoxedResidueParams::new(BoxedUint::from(3u8)).unwrap(); + BoxedMontyParams::new(BoxedUint::from(3u8)).unwrap(); } } diff --git a/src/modular/boxed_residue/add.rs b/src/modular/boxed_monty_form/add.rs similarity index 51% rename from src/modular/boxed_residue/add.rs rename to src/modular/boxed_monty_form/add.rs index 7af248fab..63aca6c85 100644 --- a/src/modular/boxed_residue/add.rs +++ b/src/modular/boxed_monty_form/add.rs @@ -1,63 +1,63 @@ -//! Additions between boxed residues. +//! Additions between boxed Montgoemery form integers. -use super::BoxedResidue; +use super::BoxedMontyForm; use core::ops::{Add, AddAssign}; -impl BoxedResidue { +impl BoxedMontyForm { /// Adds `rhs`. pub fn add(&self, rhs: &Self) -> Self { - debug_assert_eq!(self.residue_params, rhs.residue_params); + debug_assert_eq!(self.params, rhs.params); Self { montgomery_form: self .montgomery_form - .add_mod(&rhs.montgomery_form, &self.residue_params.modulus), - residue_params: self.residue_params.clone(), + .add_mod(&rhs.montgomery_form, &self.params.modulus), + params: self.params.clone(), } } } -impl Add<&BoxedResidue> for &BoxedResidue { - type Output = BoxedResidue; - fn add(self, rhs: &BoxedResidue) -> BoxedResidue { +impl Add<&BoxedMontyForm> for &BoxedMontyForm { + type Output = BoxedMontyForm; + fn add(self, rhs: &BoxedMontyForm) -> BoxedMontyForm { self.add(rhs) } } -impl Add for &BoxedResidue { - type Output = BoxedResidue; +impl Add for &BoxedMontyForm { + type Output = BoxedMontyForm; #[allow(clippy::op_ref)] - fn add(self, rhs: BoxedResidue) -> BoxedResidue { + fn add(self, rhs: BoxedMontyForm) -> BoxedMontyForm { self + &rhs } } -impl Add<&BoxedResidue> for BoxedResidue { - type Output = BoxedResidue; +impl Add<&BoxedMontyForm> for BoxedMontyForm { + type Output = BoxedMontyForm; #[allow(clippy::op_ref)] - fn add(self, rhs: &BoxedResidue) -> BoxedResidue { + fn add(self, rhs: &BoxedMontyForm) -> BoxedMontyForm { &self + rhs } } -impl Add for BoxedResidue { - type Output = BoxedResidue; - fn add(self, rhs: BoxedResidue) -> BoxedResidue { +impl Add for BoxedMontyForm { + type Output = BoxedMontyForm; + fn add(self, rhs: BoxedMontyForm) -> BoxedMontyForm { &self + &rhs } } -impl AddAssign<&BoxedResidue> for BoxedResidue { - fn add_assign(&mut self, rhs: &BoxedResidue) { - debug_assert_eq!(self.residue_params, rhs.residue_params); +impl AddAssign<&BoxedMontyForm> for BoxedMontyForm { + fn add_assign(&mut self, rhs: &BoxedMontyForm) { + debug_assert_eq!(self.params, rhs.params); self.montgomery_form = self .montgomery_form - .add_mod(&rhs.montgomery_form, &self.residue_params.modulus) + .add_mod(&rhs.montgomery_form, &self.params.modulus) } } -impl AddAssign for BoxedResidue { - fn add_assign(&mut self, rhs: BoxedResidue) { +impl AddAssign for BoxedMontyForm { + fn add_assign(&mut self, rhs: BoxedMontyForm) { *self += &rhs; } } @@ -65,14 +65,14 @@ impl AddAssign for BoxedResidue { #[cfg(test)] mod tests { use crate::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, }; use hex_literal::hex; #[test] fn add_overflow() { - let params = BoxedResidueParams::new( + let params = BoxedMontyParams::new( BoxedUint::from_be_slice( &hex!("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"), 256, @@ -86,14 +86,14 @@ mod tests { 256, ) .unwrap(); - let mut x_mod = BoxedResidue::new(x, params.clone()); + let mut x_mod = BoxedMontyForm::new(x, params.clone()); let y = BoxedUint::from_be_slice( &hex!("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"), 256, ) .unwrap(); - let y_mod = BoxedResidue::new(y, params.clone()); + let y_mod = BoxedMontyForm::new(y, params.clone()); x_mod += &y_mod; diff --git a/src/modular/boxed_residue/inv.rs b/src/modular/boxed_monty_form/inv.rs similarity index 60% rename from src/modular/boxed_residue/inv.rs rename to src/modular/boxed_monty_form/inv.rs index 5b49a1ddb..a853dbd2b 100644 --- a/src/modular/boxed_residue/inv.rs +++ b/src/modular/boxed_monty_form/inv.rs @@ -1,36 +1,34 @@ -//! Multiplicative inverses of boxed residue. +//! Multiplicative inverses of boxed integers in Montgomery form. -use super::BoxedResidue; +use super::BoxedMontyForm; use crate::{modular::reduction::montgomery_reduction_boxed_mut, Invert}; use subtle::CtOption; -impl BoxedResidue { - /// Computes the residue `self^-1` representing the multiplicative inverse of `self`. +impl BoxedMontyForm { + /// Computes `self^-1` representing the multiplicative inverse of `self`. /// I.e. `self * self^-1 = 1`. pub fn invert(&self) -> CtOption { - let (mut inverse, is_some) = self - .montgomery_form - .inv_odd_mod(&self.residue_params.modulus); + let (mut inverse, is_some) = self.montgomery_form.inv_odd_mod(&self.params.modulus); - let mut product = inverse.mul(&self.residue_params.r3); + let mut product = inverse.mul(&self.params.r3); montgomery_reduction_boxed_mut( &mut product, - &self.residue_params.modulus, - self.residue_params.mod_neg_inv, + &self.params.modulus, + self.params.mod_neg_inv, &mut inverse, ); let value = Self { montgomery_form: inverse, - residue_params: self.residue_params.clone(), + params: self.params.clone(), }; CtOption::new(value, is_some) } } -impl Invert for BoxedResidue { +impl Invert for BoxedMontyForm { type Output = CtOption; fn invert(&self) -> Self::Output { self.invert() @@ -40,13 +38,13 @@ impl Invert for BoxedResidue { #[cfg(test)] mod tests { use crate::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, }; use hex_literal::hex; - fn residue_params() -> BoxedResidueParams { - BoxedResidueParams::new( + fn monty_params() -> BoxedMontyParams { + BoxedMontyParams::new( BoxedUint::from_be_slice( &hex!("15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409"), 256, @@ -58,13 +56,13 @@ mod tests { #[test] fn test_self_inverse() { - let params = residue_params(); + let params = monty_params(); let x = BoxedUint::from_be_slice( &hex!("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"), 256, ) .unwrap(); - let x_mod = BoxedResidue::new(x, params); + let x_mod = BoxedMontyForm::new(x, params); let inv = x_mod.invert().unwrap(); let res = x_mod * inv; diff --git a/src/modular/boxed_residue/mul.rs b/src/modular/boxed_monty_form/mul.rs similarity index 82% rename from src/modular/boxed_residue/mul.rs rename to src/modular/boxed_monty_form/mul.rs index 0c4783829..9a5efcb24 100644 --- a/src/modular/boxed_residue/mul.rs +++ b/src/modular/boxed_monty_form/mul.rs @@ -1,11 +1,11 @@ -//! Multiplication between boxed residues (i.e. Montgomery multiplication). +//! Multiplication between boxed integers in Montgomery form (i.e. Montgomery multiplication). //! //! Some parts adapted from `monty.rs` in `num-bigint`: //! //! //! Originally (c) 2014 The Rust Project Developers, dual licensed Apache 2.0+MIT. -use super::{BoxedResidue, BoxedResidueParams}; +use super::{BoxedMontyForm, BoxedMontyParams}; use crate::{ modular::reduction::montgomery_reduction_boxed_mut, traits::Square, uint::mul::mul_limbs, BoxedUint, Limb, Word, Zero, @@ -19,84 +19,84 @@ use subtle::{ConditionallySelectable, ConstantTimeLess}; #[cfg(feature = "zeroize")] use zeroize::Zeroize; -impl BoxedResidue { +impl BoxedMontyForm { /// Multiplies by `rhs`. pub fn mul(&self, rhs: &Self) -> Self { - debug_assert_eq!(&self.residue_params, &rhs.residue_params); - let montgomery_form = MontgomeryMultiplier::from(self.residue_params.borrow()) + debug_assert_eq!(&self.params, &rhs.params); + let montgomery_form = MontgomeryMultiplier::from(self.params.borrow()) .mul(&self.montgomery_form, &rhs.montgomery_form); Self { montgomery_form, - residue_params: self.residue_params.clone(), + params: self.params.clone(), } } - /// Computes the (reduced) square of a residue. + /// Computes the (reduced) square. pub fn square(&self) -> Self { let montgomery_form = - MontgomeryMultiplier::from(self.residue_params.borrow()).square(&self.montgomery_form); + MontgomeryMultiplier::from(self.params.borrow()).square(&self.montgomery_form); Self { montgomery_form, - residue_params: self.residue_params.clone(), + params: self.params.clone(), } } } -impl Mul<&BoxedResidue> for &BoxedResidue { - type Output = BoxedResidue; - fn mul(self, rhs: &BoxedResidue) -> BoxedResidue { +impl Mul<&BoxedMontyForm> for &BoxedMontyForm { + type Output = BoxedMontyForm; + fn mul(self, rhs: &BoxedMontyForm) -> BoxedMontyForm { self.mul(rhs) } } -impl Mul for &BoxedResidue { - type Output = BoxedResidue; +impl Mul for &BoxedMontyForm { + type Output = BoxedMontyForm; #[allow(clippy::op_ref)] - fn mul(self, rhs: BoxedResidue) -> BoxedResidue { + fn mul(self, rhs: BoxedMontyForm) -> BoxedMontyForm { self * &rhs } } -impl Mul<&BoxedResidue> for BoxedResidue { - type Output = BoxedResidue; +impl Mul<&BoxedMontyForm> for BoxedMontyForm { + type Output = BoxedMontyForm; #[allow(clippy::op_ref)] - fn mul(self, rhs: &BoxedResidue) -> BoxedResidue { + fn mul(self, rhs: &BoxedMontyForm) -> BoxedMontyForm { &self * rhs } } -impl Mul for BoxedResidue { - type Output = BoxedResidue; - fn mul(self, rhs: BoxedResidue) -> BoxedResidue { +impl Mul for BoxedMontyForm { + type Output = BoxedMontyForm; + fn mul(self, rhs: BoxedMontyForm) -> BoxedMontyForm { &self * &rhs } } -impl MulAssign for BoxedResidue { - fn mul_assign(&mut self, rhs: BoxedResidue) { +impl MulAssign for BoxedMontyForm { + fn mul_assign(&mut self, rhs: BoxedMontyForm) { Self::mul_assign(self, &rhs) } } -impl MulAssign<&BoxedResidue> for BoxedResidue { - fn mul_assign(&mut self, rhs: &BoxedResidue) { - debug_assert_eq!(&self.residue_params, &rhs.residue_params); - MontgomeryMultiplier::from(self.residue_params.borrow()) +impl MulAssign<&BoxedMontyForm> for BoxedMontyForm { + fn mul_assign(&mut self, rhs: &BoxedMontyForm) { + debug_assert_eq!(&self.params, &rhs.params); + MontgomeryMultiplier::from(self.params.borrow()) .mul_assign(&mut self.montgomery_form, &rhs.montgomery_form); } } -impl Square for BoxedResidue { +impl Square for BoxedMontyForm { fn square(&self) -> Self { - BoxedResidue::square(self) + BoxedMontyForm::square(self) } } -impl<'a> From<&'a BoxedResidueParams> for MontgomeryMultiplier<'a> { - fn from(residue_params: &'a BoxedResidueParams) -> MontgomeryMultiplier<'a> { - MontgomeryMultiplier::new(&residue_params.modulus, residue_params.mod_neg_inv) +impl<'a> From<&'a BoxedMontyParams> for MontgomeryMultiplier<'a> { + fn from(params: &'a BoxedMontyParams) -> MontgomeryMultiplier<'a> { + MontgomeryMultiplier::new(¶ms.modulus, params.mod_neg_inv) } } @@ -245,7 +245,7 @@ impl Drop for MontgomeryMultiplier<'_> { /// Output is written into the lower (i.e. first) half of `z`. /// /// Note: this was adapted from an implementation in `num-bigint`'s `monty.rs`. -// TODO(tarcieri): refactor into `reduction.rs`, share impl with `(Dyn)Residue`? +// TODO(tarcieri): refactor into `reduction.rs`, share impl with `MontyForm`? fn almost_montgomery_mul(z: &mut [Limb], x: &[Limb], y: &[Limb], m: &[Limb], k: Limb) { // This code assumes x, y, m are all the same length (required by addMulVVW and the for loop). // It also assumes that x, y are already reduced mod m, or else the result will not be properly @@ -306,18 +306,18 @@ fn sub_vv(z: &mut [Limb], x: &[Limb], y: &[Limb]) { #[cfg(test)] mod tests { - use super::{BoxedResidue, BoxedResidueParams, BoxedUint}; + use super::{BoxedMontyForm, BoxedMontyParams, BoxedUint}; /// Regression test for RustCrypto/crypto-bigint#441 #[test] fn square() { - let residue = 0x20u128; + let x = 0x20u128; let modulus = 0xB44677037A7DBDE04814256570DCBD8Du128; let boxed_modulus = BoxedUint::from(modulus); - let boxed_params = BoxedResidueParams::new(boxed_modulus).unwrap(); - let boxed_residue = BoxedResidue::new(BoxedUint::from(residue), boxed_params); - let boxed_square = boxed_residue.square(); + let boxed_params = BoxedMontyParams::new(boxed_modulus).unwrap(); + let boxed_monty = BoxedMontyForm::new(BoxedUint::from(x), boxed_params); + let boxed_square = boxed_monty.square(); // TODO(tarcieri): test for correct output assert!(boxed_square.as_montgomery() < boxed_square.params().modulus()); diff --git a/src/modular/boxed_monty_form/neg.rs b/src/modular/boxed_monty_form/neg.rs new file mode 100644 index 000000000..86cde7e77 --- /dev/null +++ b/src/modular/boxed_monty_form/neg.rs @@ -0,0 +1,31 @@ +//! Negations of boxed integers in Montgomery form. + +use super::BoxedMontyForm; +use crate::BoxedUint; +use core::ops::Neg; + +impl BoxedMontyForm { + /// Negates the number. + pub fn neg(&self) -> Self { + let zero = Self { + montgomery_form: BoxedUint::zero_with_precision(self.params.bits_precision()), + params: self.params.clone(), + }; + + zero.sub(self) + } +} + +impl Neg for BoxedMontyForm { + type Output = Self; + fn neg(self) -> Self { + BoxedMontyForm::neg(&self) + } +} + +impl Neg for &BoxedMontyForm { + type Output = BoxedMontyForm; + fn neg(self) -> BoxedMontyForm { + BoxedMontyForm::neg(self) + } +} diff --git a/src/modular/boxed_residue/pow.rs b/src/modular/boxed_monty_form/pow.rs similarity index 84% rename from src/modular/boxed_residue/pow.rs rename to src/modular/boxed_monty_form/pow.rs index 3d20ee3c9..7ac874b06 100644 --- a/src/modular/boxed_residue/pow.rs +++ b/src/modular/boxed_monty_form/pow.rs @@ -1,11 +1,11 @@ -//! Modular exponentiation support for [`BoxedResidue`]. +//! Modular exponentiation support for [`BoxedMontyForm`]. -use super::{mul::MontgomeryMultiplier, BoxedResidue}; +use super::{mul::MontgomeryMultiplier, BoxedMontyForm}; use crate::{BoxedUint, ConstantTimeSelect, Limb, PowBoundedExp, Word}; use alloc::vec::Vec; use subtle::{ConstantTimeEq, ConstantTimeLess}; -impl BoxedResidue { +impl BoxedMontyForm { /// Raises to the `exponent` power. pub fn pow(&self, exponent: &BoxedUint) -> Self { self.pow_bounded_exp(exponent, exponent.bits_precision()) @@ -22,19 +22,19 @@ impl BoxedResidue { &self.montgomery_form, exponent, exponent_bits, - &self.residue_params.modulus, - &self.residue_params.r, - self.residue_params.mod_neg_inv, + &self.params.modulus, + &self.params.one, + self.params.mod_neg_inv, ), - residue_params: self.residue_params.clone(), + params: self.params.clone(), }; - debug_assert!(ret.retrieve() < self.residue_params.modulus); + debug_assert!(ret.retrieve() < self.params.modulus); ret } } -impl PowBoundedExp for BoxedResidue { +impl PowBoundedExp for BoxedMontyForm { fn pow_bounded_exp(&self, exponent: &BoxedUint, exponent_bits: u32) -> Self { self.pow_bounded_exp(exponent, exponent_bits) } @@ -49,11 +49,11 @@ fn pow_montgomery_form( exponent: &BoxedUint, exponent_bits: u32, modulus: &BoxedUint, - r: &BoxedUint, + one: &BoxedUint, mod_neg_inv: Limb, ) -> BoxedUint { if exponent_bits == 0 { - return r.clone(); // 1 in Montgomery form + return one.clone(); // 1 in Montgomery form } const WINDOW: u32 = 4; @@ -63,7 +63,7 @@ fn pow_montgomery_form( // powers[i] contains x^i let mut powers = Vec::with_capacity(1 << WINDOW); - powers.push(r.clone()); // 1 in Montgomery form + powers.push(one.clone()); // 1 in Montgomery form powers.push(x.clone()); for i in 2..(1 << WINDOW) { @@ -75,7 +75,7 @@ fn pow_montgomery_form( let starting_window = starting_bit_in_limb / WINDOW; let starting_window_mask = (1 << (starting_bit_in_limb % WINDOW + 1)) - 1; - let mut z = r.clone(); // 1 in Montgomery form + let mut z = one.clone(); // 1 in Montgomery form let mut power = powers[0].clone(); for limb_num in (0..=starting_limb).rev() { diff --git a/src/modular/boxed_residue/sub.rs b/src/modular/boxed_monty_form/sub.rs similarity index 50% rename from src/modular/boxed_residue/sub.rs rename to src/modular/boxed_monty_form/sub.rs index 837274ad8..1ed0d8aa5 100644 --- a/src/modular/boxed_residue/sub.rs +++ b/src/modular/boxed_monty_form/sub.rs @@ -1,64 +1,64 @@ -//! Subtractions between boxed residues. +//! Subtractions between boxed integers in Montgomery form. -use super::BoxedResidue; +use super::BoxedMontyForm; use core::ops::{Sub, SubAssign}; -impl BoxedResidue { +impl BoxedMontyForm { /// Subtracts `rhs`. pub fn sub(&self, rhs: &Self) -> Self { - debug_assert_eq!(self.residue_params, rhs.residue_params); + debug_assert_eq!(self.params, rhs.params); Self { montgomery_form: self .montgomery_form - .sub_mod(&rhs.montgomery_form, &self.residue_params.modulus), - residue_params: self.residue_params.clone(), + .sub_mod(&rhs.montgomery_form, &self.params.modulus), + params: self.params.clone(), } } } -impl Sub<&BoxedResidue> for &BoxedResidue { - type Output = BoxedResidue; - fn sub(self, rhs: &BoxedResidue) -> BoxedResidue { - debug_assert_eq!(self.residue_params, rhs.residue_params); +impl Sub<&BoxedMontyForm> for &BoxedMontyForm { + type Output = BoxedMontyForm; + fn sub(self, rhs: &BoxedMontyForm) -> BoxedMontyForm { + debug_assert_eq!(self.params, rhs.params); self.sub(rhs) } } -impl Sub for &BoxedResidue { - type Output = BoxedResidue; +impl Sub for &BoxedMontyForm { + type Output = BoxedMontyForm; #[allow(clippy::op_ref)] - fn sub(self, rhs: BoxedResidue) -> BoxedResidue { + fn sub(self, rhs: BoxedMontyForm) -> BoxedMontyForm { self - &rhs } } -impl Sub<&BoxedResidue> for BoxedResidue { - type Output = BoxedResidue; +impl Sub<&BoxedMontyForm> for BoxedMontyForm { + type Output = BoxedMontyForm; #[allow(clippy::op_ref)] - fn sub(self, rhs: &BoxedResidue) -> BoxedResidue { + fn sub(self, rhs: &BoxedMontyForm) -> BoxedMontyForm { &self - rhs } } -impl Sub for BoxedResidue { - type Output = BoxedResidue; - fn sub(self, rhs: BoxedResidue) -> BoxedResidue { +impl Sub for BoxedMontyForm { + type Output = BoxedMontyForm; + fn sub(self, rhs: BoxedMontyForm) -> BoxedMontyForm { &self - &rhs } } -impl SubAssign<&BoxedResidue> for BoxedResidue { - fn sub_assign(&mut self, rhs: &BoxedResidue) { - debug_assert_eq!(self.residue_params, rhs.residue_params); +impl SubAssign<&BoxedMontyForm> for BoxedMontyForm { + fn sub_assign(&mut self, rhs: &BoxedMontyForm) { + debug_assert_eq!(self.params, rhs.params); self.montgomery_form = self .montgomery_form - .sub_mod(&rhs.montgomery_form, &self.residue_params.modulus) + .sub_mod(&rhs.montgomery_form, &self.params.modulus) } } -impl SubAssign for BoxedResidue { - fn sub_assign(&mut self, rhs: BoxedResidue) { +impl SubAssign for BoxedMontyForm { + fn sub_assign(&mut self, rhs: BoxedMontyForm) { *self -= &rhs; } } @@ -66,14 +66,14 @@ impl SubAssign for BoxedResidue { #[cfg(test)] mod tests { use crate::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, }; use hex_literal::hex; #[test] fn sub_overflow() { - let params = BoxedResidueParams::new( + let params = BoxedMontyParams::new( BoxedUint::from_be_slice( &hex!("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"), 256, @@ -87,14 +87,14 @@ mod tests { 256, ) .unwrap(); - let mut x_mod = BoxedResidue::new(x, params.clone()); + let mut x_mod = BoxedMontyForm::new(x, params.clone()); let y = BoxedUint::from_be_slice( &hex!("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"), 256, ) .unwrap(); - let y_mod = BoxedResidue::new(y, params); + let y_mod = BoxedMontyForm::new(y, params); x_mod -= &y_mod; diff --git a/src/modular/boxed_residue/neg.rs b/src/modular/boxed_residue/neg.rs deleted file mode 100644 index 75fe4a73d..000000000 --- a/src/modular/boxed_residue/neg.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! Negations of boxed residues. - -use super::BoxedResidue; -use crate::BoxedUint; -use core::ops::Neg; - -impl BoxedResidue { - /// Negates the number. - pub fn neg(&self) -> Self { - let zero = Self { - montgomery_form: BoxedUint::zero_with_precision(self.residue_params.bits_precision()), - residue_params: self.residue_params.clone(), - }; - - zero.sub(self) - } -} - -impl Neg for BoxedResidue { - type Output = Self; - fn neg(self) -> Self { - BoxedResidue::neg(&self) - } -} - -impl Neg for &BoxedResidue { - type Output = BoxedResidue; - fn neg(self) -> BoxedResidue { - BoxedResidue::neg(self) - } -} diff --git a/src/modular/residue.rs b/src/modular/const_monty_form.rs similarity index 66% rename from src/modular/residue.rs rename to src/modular/const_monty_form.rs index 328790cf0..88446fd90 100644 --- a/src/modular/residue.rs +++ b/src/modular/const_monty_form.rs @@ -1,4 +1,4 @@ -//! Implements `Residue`s, supporting modular arithmetic with a constant modulus. +//! Implements `ConstMontyForm`s, supporting modular arithmetic with a constant modulus. mod add; pub(super) mod inv; @@ -7,7 +7,7 @@ mod neg; mod pow; mod sub; -use self::inv::ResidueInverter; +use self::inv::ConstMontyFormInverter; use super::{div_by_2::div_by_2, reduction::montgomery_reduction, BernsteinYangInverter, Retrieve}; use crate::{Limb, NonZero, PrecomputeInverter, Uint, ZeroConstant}; use core::{fmt::Debug, marker::PhantomData}; @@ -32,19 +32,19 @@ mod macros; /// macro. These parameters are constant, so they cannot be set at runtime. /// /// Unfortunately, `LIMBS` must be generic for now until const generics are stabilized. -pub trait ResidueParams: +pub trait ConstMontyParams: Copy + Debug + Default + Eq + Send + Sync + 'static { - /// Number of limbs required to encode a residue + /// Number of limbs required to encode the Montgomery form const LIMBS: usize; /// The constant modulus const MODULUS: NonZero>; - /// Parameter used in Montgomery reduction - const R: Uint; - /// R^2, used to move into Montgomery form + /// 1 in Montgomery form + const ONE: Uint; + /// `R^2 mod MODULUS`, used to move into Montgomery form const R2: Uint; - /// R^3, used to perform a multiplicative inverse + /// `R^3 mod MODULUS`, used to perform a multiplicative inverse const R3: Uint; /// The lowest limbs of -(MODULUS^-1) mod R // We only need the LSB because during reduction this value is multiplied modulo 2**Limb::BITS. @@ -52,35 +52,35 @@ pub trait ResidueParams: /// Precompute a Bernstein-Yang inverter for this modulus. /// - /// Use [`ResidueInverter::new`] if you need `const fn` access. - fn precompute_inverter() -> ResidueInverter + /// Use [`ConstMontyFormInverter::new`] if you need `const fn` access. + fn precompute_inverter() -> ConstMontyFormInverter where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, Output = Uint, >, { - ResidueInverter::new() + ConstMontyFormInverter::new() } } -/// A residue mod `MOD`, represented using `LIMBS` limbs. The modulus of this residue is constant, -/// so it cannot be set at runtime. +/// An integer in Montgomery form modulo `MOD`, represented using `LIMBS` limbs. +/// The modulus is constant, so it cannot be set at runtime. /// -/// Internally, the value is stored in Montgomery form (multiplied by MOD::R) until it is retrieved. +/// Internally, the value is stored in Montgomery form (multiplied by MOD::ONE) until it is retrieved. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Residue, const LIMBS: usize> { +pub struct ConstMontyForm, const LIMBS: usize> { montgomery_form: Uint, phantom: PhantomData, } #[cfg(feature = "zeroize")] -impl, const LIMBS: usize> zeroize::DefaultIsZeroes - for Residue +impl, const LIMBS: usize> zeroize::DefaultIsZeroes + for ConstMontyForm { } -impl, const LIMBS: usize> Residue { +impl, const LIMBS: usize> ConstMontyForm { /// The representation of 0 mod `MOD`. pub const ZERO: Self = Self { montgomery_form: Uint::::ZERO, @@ -89,12 +89,13 @@ impl, const LIMBS: usize> Residue { /// The representation of 1 mod `MOD`. pub const ONE: Self = Self { - montgomery_form: MOD::R, + montgomery_form: MOD::ONE, phantom: PhantomData, }; - /// Internal helper function to generate a residue; this lets us cleanly wrap the constructors. - const fn generate_residue(integer: &Uint) -> Self { + /// Internal helper function to convert to Montgomery form; + /// this lets us cleanly wrap the constructors. + const fn from_integer(integer: &Uint) -> Self { let product = integer.split_mul(&MOD::R2); let montgomery_form = montgomery_reduction::(&product, &MOD::MODULUS.0, MOD::MOD_NEG_INV); @@ -105,12 +106,12 @@ impl, const LIMBS: usize> Residue { } } - /// Instantiates a new [`Residue`] that represents this `integer` mod `MOD`. + /// Instantiates a new [`ConstMontyForm`] that represents this `integer` mod `MOD`. pub const fn new(integer: &Uint) -> Self { - Self::generate_residue(integer) + Self::from_integer(integer) } - /// Retrieves the integer currently encoded in this [`Residue`], guaranteed to be reduced. + /// Retrieves the integer currently encoded in this [`ConstMontyForm`], guaranteed to be reduced. pub const fn retrieve(&self) -> Uint { montgomery_reduction::( &(self.montgomery_form, Uint::ZERO), @@ -119,17 +120,17 @@ impl, const LIMBS: usize> Residue { ) } - /// Access the `Residue` value in Montgomery form. + /// Access the `ConstMontyForm` value in Montgomery form. pub const fn as_montgomery(&self) -> &Uint { &self.montgomery_form } - /// Mutably access the `Residue` value in Montgomery form. + /// Mutably access the `ConstMontyForm` value in Montgomery form. pub fn as_montgomery_mut(&mut self) -> &mut Uint { &mut self.montgomery_form } - /// Create a `Residue` from a value in Montgomery form. + /// Create a `ConstMontyForm` from a value in Montgomery form. pub const fn from_montgomery(integer: Uint) -> Self { Self { montgomery_form: integer, @@ -137,7 +138,7 @@ impl, const LIMBS: usize> Residue { } } - /// Extract the value from the `Residue` in Montgomery form. + /// Extract the value from the `ConstMontyForm` in Montgomery form. pub const fn to_montgomery(&self) -> Uint { self.montgomery_form } @@ -155,11 +156,11 @@ impl, const LIMBS: usize> Residue { } } -impl + Copy, const LIMBS: usize> ConditionallySelectable - for Residue +impl + Copy, const LIMBS: usize> ConditionallySelectable + for ConstMontyForm { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - Residue { + ConstMontyForm { montgomery_form: Uint::conditional_select( &a.montgomery_form, &b.montgomery_form, @@ -170,26 +171,28 @@ impl + Copy, const LIMBS: usize> ConditionallySelectab } } -impl, const LIMBS: usize> ConstantTimeEq for Residue { +impl, const LIMBS: usize> ConstantTimeEq + for ConstMontyForm +{ fn ct_eq(&self, other: &Self) -> Choice { ConstantTimeEq::ct_eq(&self.montgomery_form, &other.montgomery_form) } } -impl, const LIMBS: usize> Default for Residue { +impl, const LIMBS: usize> Default for ConstMontyForm { fn default() -> Self { Self::ZERO } } -impl, const LIMBS: usize> ZeroConstant for Residue { +impl, const LIMBS: usize> ZeroConstant for ConstMontyForm { const ZERO: Self = Self::ZERO; } #[cfg(feature = "rand_core")] -impl Random for Residue +impl Random for ConstMontyForm where - MOD: ResidueParams, + MOD: ConstMontyParams, { #[inline] fn random(rng: &mut impl CryptoRngCore) -> Self { @@ -197,7 +200,7 @@ where } } -impl, const LIMBS: usize> Retrieve for Residue { +impl, const LIMBS: usize> Retrieve for ConstMontyForm { type Output = Uint; fn retrieve(&self) -> Self::Output { self.retrieve() @@ -205,9 +208,9 @@ impl, const LIMBS: usize> Retrieve for Residue Deserialize<'de> for Residue +impl<'de, MOD, const LIMBS: usize> Deserialize<'de> for ConstMontyForm where - MOD: ResidueParams, + MOD: ConstMontyParams, Uint: Encoding, { fn deserialize(deserializer: D) -> Result @@ -228,9 +231,9 @@ where } #[cfg(feature = "serde")] -impl Serialize for Residue +impl Serialize for ConstMontyForm where - MOD: ResidueParams, + MOD: ConstMontyParams, Uint: Encoding, { fn serialize(&self, serializer: S) -> Result diff --git a/src/modular/const_monty_form/add.rs b/src/modular/const_monty_form/add.rs new file mode 100644 index 000000000..2aeedbce5 --- /dev/null +++ b/src/modular/const_monty_form/add.rs @@ -0,0 +1,104 @@ +//! Additions between integers in Montgomery form with a constant modulus. + +use super::{ConstMontyForm, ConstMontyParams}; +use crate::modular::add::add_montgomery_form; +use core::ops::{Add, AddAssign}; + +impl, const LIMBS: usize> ConstMontyForm { + /// Adds `rhs`. + pub const fn add(&self, rhs: &ConstMontyForm) -> Self { + Self { + montgomery_form: add_montgomery_form( + &self.montgomery_form, + &rhs.montgomery_form, + &MOD::MODULUS.0, + ), + phantom: core::marker::PhantomData, + } + } +} + +impl, const LIMBS: usize> Add<&ConstMontyForm> + for &ConstMontyForm +{ + type Output = ConstMontyForm; + fn add(self, rhs: &ConstMontyForm) -> ConstMontyForm { + self.add(rhs) + } +} + +impl, const LIMBS: usize> Add> + for &ConstMontyForm +{ + type Output = ConstMontyForm; + #[allow(clippy::op_ref)] + fn add(self, rhs: ConstMontyForm) -> ConstMontyForm { + self + &rhs + } +} + +impl, const LIMBS: usize> Add<&ConstMontyForm> + for ConstMontyForm +{ + type Output = ConstMontyForm; + #[allow(clippy::op_ref)] + fn add(self, rhs: &ConstMontyForm) -> ConstMontyForm { + &self + rhs + } +} + +impl, const LIMBS: usize> Add> + for ConstMontyForm +{ + type Output = ConstMontyForm; + fn add(self, rhs: ConstMontyForm) -> ConstMontyForm { + &self + &rhs + } +} + +impl, const LIMBS: usize> AddAssign<&Self> + for ConstMontyForm +{ + fn add_assign(&mut self, rhs: &Self) { + *self = *self + rhs; + } +} + +impl, const LIMBS: usize> AddAssign + for ConstMontyForm +{ + fn add_assign(&mut self, rhs: Self) { + *self += &rhs; + } +} + +#[cfg(test)] +mod tests { + use crate::{ + const_monty_form, impl_modulus, modular::const_monty_form::ConstMontyParams, U256, + }; + + impl_modulus!( + Modulus, + U256, + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" + ); + + #[test] + fn add_overflow() { + let x = + U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); + let mut x_mod = const_monty_form!(x, Modulus); + + let y = + U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); + let y_mod = const_monty_form!(y, Modulus); + + x_mod += &y_mod; + + let expected = + U256::from_be_hex("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956"); + + assert_eq!(expected, x_mod.retrieve()); + } +} diff --git a/src/modular/residue/inv.rs b/src/modular/const_monty_form/inv.rs similarity index 69% rename from src/modular/residue/inv.rs rename to src/modular/const_monty_form/inv.rs index 6379c8e44..314adbff9 100644 --- a/src/modular/residue/inv.rs +++ b/src/modular/const_monty_form/inv.rs @@ -1,21 +1,21 @@ -//! Multiplicative inverses of residues with a constant modulus. +//! Multiplicative inverses of integers in Montgomery form with a constant modulus. -use super::{Residue, ResidueParams}; +use super::{ConstMontyForm, ConstMontyParams}; use crate::{ modular::BernsteinYangInverter, ConstCtOption, Invert, Inverter, PrecomputeInverter, Uint, }; use core::{fmt, marker::PhantomData}; use subtle::CtOption; -impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> - Residue +impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> + ConstMontyForm where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, Output = Uint, >, { - /// Computes the residue `self^-1` representing the multiplicative inverse of `self`. + /// 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). @@ -36,8 +36,8 @@ where } } -impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Invert - for Residue +impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Invert + for ConstMontyForm where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, @@ -50,8 +50,8 @@ where } } -/// Bernstein-Yang inverter which inverts [`Residue`] types. -pub struct ResidueInverter, const LIMBS: usize> +/// Bernstein-Yang inverter which inverts [`ConstMontyForm`] types. +pub struct ConstMontyFormInverter, const LIMBS: usize> where Uint: PrecomputeInverter>, { @@ -59,15 +59,15 @@ where phantom: PhantomData, } -impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> - ResidueInverter +impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> + ConstMontyFormInverter where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, Output = Uint, >, { - /// Create a new [`ResidueInverter`] for the given [`ResidueParams`]. + /// Create a new [`ConstMontyFormInverter`] for the given [`ConstMontyParams`]. pub const fn new() -> Self { let inverter = BernsteinYangInverter::new(&MOD::MODULUS.0, &MOD::R2).expect("modulus should be valid"); @@ -82,11 +82,11 @@ where /// depending on invertibility of the argument, i.e. its coprimality with the modulus. pub const fn inv( &self, - value: &Residue, - ) -> ConstCtOption> { + value: &ConstMontyForm, + ) -> ConstCtOption> { let montgomery_form = self.inverter.inv(&value.montgomery_form); let (montgomery_form_ref, is_some) = montgomery_form.components_ref(); - let ret = Residue { + let ret = ConstMontyForm { montgomery_form: *montgomery_form_ref, phantom: PhantomData, }; @@ -94,23 +94,23 @@ where } } -impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Inverter - for ResidueInverter +impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> Inverter + for ConstMontyFormInverter where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, Output = Uint, >, { - type Output = Residue; + type Output = ConstMontyForm; - fn invert(&self, value: &Residue) -> CtOption { + fn invert(&self, value: &ConstMontyForm) -> CtOption { self.inv(value).into() } } -impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> fmt::Debug - for ResidueInverter +impl, const SAT_LIMBS: usize, const UNSAT_LIMBS: usize> fmt::Debug + for ConstMontyFormInverter where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, @@ -118,7 +118,7 @@ where >, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ResidueInverter") + f.debug_struct("ConstMontyFormInverter") .field("modulus", &self.inverter.modulus) .finish() } @@ -126,8 +126,8 @@ where #[cfg(test)] mod tests { - use super::ResidueParams; - use crate::{const_residue, impl_modulus, Inverter, U256}; + use super::ConstMontyParams; + use crate::{const_monty_form, impl_modulus, Inverter, U256}; impl_modulus!( Modulus, @@ -139,7 +139,7 @@ mod tests { fn test_self_inverse() { let x = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); - let x_mod = const_residue!(x, Modulus); + let x_mod = const_monty_form!(x, Modulus); let inv = x_mod.inv().unwrap(); let res = x_mod * inv; @@ -151,7 +151,7 @@ mod tests { fn test_self_inverse_precomputed() { let x = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); - let x_mod = const_residue!(x, Modulus); + let x_mod = const_monty_form!(x, Modulus); let inverter = Modulus::precompute_inverter(); let inv = inverter.invert(&x_mod).unwrap(); diff --git a/src/modular/residue/macros.rs b/src/modular/const_monty_form/macros.rs similarity index 70% rename from src/modular/residue/macros.rs rename to src/modular/const_monty_form/macros.rs index 07d0454c3..d6adcbee3 100644 --- a/src/modular/residue/macros.rs +++ b/src/modular/const_monty_form/macros.rs @@ -8,14 +8,15 @@ /// implements a 256-bit modulus named `MyModulus`. /// /// The modulus _must_ be odd, or this will panic. -// TODO: Use `adt_const_params` once stabilized to make a `Residue` generic around a modulus rather +// TODO: Use `adt_const_params` once stabilized to make a `ConstMontyForm` generic around a modulus rather // than having to implement a ZST + trait #[macro_export] macro_rules! impl_modulus { ($name:ident, $uint_type:ty, $value:expr) => { #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub struct $name; - impl $crate::modular::ResidueParams<{ <$uint_type>::LIMBS }> for $name + impl $crate::modular::ConstMontyParams<{ <$uint_type>::LIMBS }> + for $name where $uint_type: $crate::ConcatMixed>, { @@ -32,11 +33,16 @@ macro_rules! impl_modulus { res.to_nz().expect("modulus ensured non-zero") }; - const R: $uint_type = $crate::Uint::MAX + // `R mod MODULUS` where `R = 2^BITS`. + // Represents 1 in Montgomery form. + const ONE: $uint_type = $crate::Uint::MAX .rem_vartime(&Self::MODULUS) .wrapping_add(&$crate::Uint::ONE); + + // `R^2 mod MODULUS`, used to convert integers to Montgomery form. const R2: $uint_type = - $crate::Uint::rem_wide_vartime(Self::R.square_wide(), &Self::MODULUS); + $crate::Uint::rem_wide_vartime(Self::ONE.square_wide(), &Self::MODULUS); + const MOD_NEG_INV: $crate::Limb = $crate::Limb( $crate::Word::MIN.wrapping_sub( Self::MODULUS @@ -47,6 +53,7 @@ macro_rules! impl_modulus { .0, ), ); + const R3: $uint_type = $crate::modular::montgomery_reduction( &Self::R2.square_wide(), Self::MODULUS.as_ref(), @@ -56,15 +63,15 @@ macro_rules! impl_modulus { }; } -/// Creates a `Residue` with the given value for a specific modulus. +/// Creates a `ConstMontyForm` with the given value for a specific modulus. /// -/// For example, `residue!(U256::from(105u64), MyModulus);` creates a `Residue` for 105 mod -/// `MyModulus`. +/// For example, `const_monty_form!(U256::from(105u64), MyModulus);` +/// creates a `ConstMontyForm` for 105 mod `MyModulus`. /// /// The modulus _must_ be odd, or this will panic. #[macro_export] -macro_rules! const_residue { +macro_rules! const_monty_form { ($variable:ident, $modulus:ident) => { - $crate::modular::Residue::<$modulus, { $modulus::LIMBS }>::new(&$variable) + $crate::modular::ConstMontyForm::<$modulus, { $modulus::LIMBS }>::new(&$variable) }; } diff --git a/src/modular/const_monty_form/mul.rs b/src/modular/const_monty_form/mul.rs new file mode 100644 index 000000000..8d78cb391 --- /dev/null +++ b/src/modular/const_monty_form/mul.rs @@ -0,0 +1,100 @@ +//! Multiplications between integers in Montgomery form with a constant modulus. + +use core::{ + marker::PhantomData, + ops::{Mul, MulAssign}, +}; + +use crate::{ + modular::mul::{mul_montgomery_form, square_montgomery_form}, + traits::Square, +}; + +use super::{ConstMontyForm, ConstMontyParams}; + +impl, const LIMBS: usize> ConstMontyForm { + /// Multiplies by `rhs`. + pub const fn mul(&self, rhs: &Self) -> Self { + Self { + montgomery_form: mul_montgomery_form( + &self.montgomery_form, + &rhs.montgomery_form, + &MOD::MODULUS.0, + MOD::MOD_NEG_INV, + ), + phantom: PhantomData, + } + } + + /// Computes the (reduced) square. + pub const fn square(&self) -> Self { + Self { + montgomery_form: square_montgomery_form( + &self.montgomery_form, + &MOD::MODULUS.0, + MOD::MOD_NEG_INV, + ), + phantom: PhantomData, + } + } +} + +impl, const LIMBS: usize> Mul<&ConstMontyForm> + for &ConstMontyForm +{ + type Output = ConstMontyForm; + fn mul(self, rhs: &ConstMontyForm) -> ConstMontyForm { + self.mul(rhs) + } +} + +impl, const LIMBS: usize> Mul> + for &ConstMontyForm +{ + type Output = ConstMontyForm; + #[allow(clippy::op_ref)] + fn mul(self, rhs: ConstMontyForm) -> ConstMontyForm { + self * &rhs + } +} + +impl, const LIMBS: usize> Mul<&ConstMontyForm> + for ConstMontyForm +{ + type Output = ConstMontyForm; + #[allow(clippy::op_ref)] + fn mul(self, rhs: &ConstMontyForm) -> ConstMontyForm { + &self * rhs + } +} + +impl, const LIMBS: usize> Mul> + for ConstMontyForm +{ + type Output = ConstMontyForm; + fn mul(self, rhs: ConstMontyForm) -> ConstMontyForm { + &self * &rhs + } +} + +impl, const LIMBS: usize> MulAssign<&Self> + for ConstMontyForm +{ + fn mul_assign(&mut self, rhs: &ConstMontyForm) { + *self = *self * rhs; + } +} + +impl, const LIMBS: usize> MulAssign + for ConstMontyForm +{ + fn mul_assign(&mut self, rhs: Self) { + *self *= &rhs; + } +} + +impl, const LIMBS: usize> Square for ConstMontyForm { + fn square(&self) -> Self { + ConstMontyForm::square(self) + } +} diff --git a/src/modular/const_monty_form/neg.rs b/src/modular/const_monty_form/neg.rs new file mode 100644 index 000000000..e1396abf9 --- /dev/null +++ b/src/modular/const_monty_form/neg.rs @@ -0,0 +1,51 @@ +//! Negations of integers in Montgomery form with a constant modulus. + +use super::{ConstMontyForm, ConstMontyParams}; +use core::ops::Neg; + +impl, const LIMBS: usize> ConstMontyForm { + /// Negates the number. + pub const fn neg(&self) -> Self { + Self::ZERO.sub(self) + } +} + +impl, const LIMBS: usize> Neg for ConstMontyForm { + type Output = Self; + fn neg(self) -> Self { + ConstMontyForm::neg(&self) + } +} + +impl, const LIMBS: usize> Neg for &ConstMontyForm { + type Output = ConstMontyForm; + fn neg(self) -> ConstMontyForm { + ConstMontyForm::neg(self) + } +} + +#[cfg(test)] +mod tests { + use crate::{ + const_monty_form, impl_modulus, modular::const_monty_form::ConstMontyParams, U256, + }; + + impl_modulus!( + Modulus, + U256, + "15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409" + ); + + #[test] + fn test_negate() { + let x = + U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); + let x_mod = const_monty_form!(x, Modulus); + + let res = -x_mod; + let expected = + U256::from_be_hex("089B67BB2C124F084701AD76E8750D321385E35044C74CE457301A2A9BE061B1"); + + assert_eq!(res.retrieve(), expected); + } +} diff --git a/src/modular/residue/pow.rs b/src/modular/const_monty_form/pow.rs similarity index 78% rename from src/modular/residue/pow.rs rename to src/modular/const_monty_form/pow.rs index 05303d110..6d9aea0d5 100644 --- a/src/modular/residue/pow.rs +++ b/src/modular/const_monty_form/pow.rs @@ -1,6 +1,6 @@ -//! Exponentiation of residues with a constant modulus. +//! Exponentiation of integers in Montgomery form with a constant modulus. -use super::{Residue, ResidueParams}; +use super::{ConstMontyForm, ConstMontyParams}; use crate::{ modular::pow::{multi_exponentiate_montgomery_form_array, pow_montgomery_form}, MultiExponentiateBoundedExp, PowBoundedExp, Uint, @@ -9,12 +9,12 @@ use crate::{ #[cfg(feature = "alloc")] use {crate::modular::pow::multi_exponentiate_montgomery_form_slice, alloc::vec::Vec}; -impl, const LIMBS: usize> Residue { +impl, const LIMBS: usize> ConstMontyForm { /// Raises to the `exponent` power. pub const fn pow( &self, exponent: &Uint, - ) -> Residue { + ) -> ConstMontyForm { self.pow_bounded_exp(exponent, Uint::::BITS) } @@ -27,14 +27,14 @@ impl, const LIMBS: usize> Residue { &self, exponent: &Uint, exponent_bits: u32, - ) -> Residue { + ) -> ConstMontyForm { Self { montgomery_form: pow_montgomery_form( &self.montgomery_form, exponent, exponent_bits, &MOD::MODULUS.0, - &MOD::R, + &MOD::ONE, MOD::MOD_NEG_INV, ), phantom: core::marker::PhantomData, @@ -42,17 +42,17 @@ impl, const LIMBS: usize> Residue { } } -impl, const LIMBS: usize, const RHS_LIMBS: usize> - PowBoundedExp> for Residue +impl, const LIMBS: usize, const RHS_LIMBS: usize> + PowBoundedExp> for ConstMontyForm { fn pow_bounded_exp(&self, exponent: &Uint, exponent_bits: u32) -> Self { self.pow_bounded_exp(exponent, exponent_bits) } } -impl, const LIMBS: usize, const RHS_LIMBS: usize> +impl, const LIMBS: usize, const RHS_LIMBS: usize> MultiExponentiateBoundedExp, [(Self, Uint); N]> - for Residue + for ConstMontyForm { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint); N], @@ -73,7 +73,7 @@ impl, const LIMBS: usize, const RHS_LI &bases_and_exponents_montgomery_form, exponent_bits, &MOD::MODULUS, - &MOD::R, + &MOD::ONE, MOD::MOD_NEG_INV, ), phantom: core::marker::PhantomData, @@ -82,9 +82,9 @@ impl, const LIMBS: usize, const RHS_LI } #[cfg(feature = "alloc")] -impl, const LIMBS: usize, const RHS_LIMBS: usize> +impl, const LIMBS: usize, const RHS_LIMBS: usize> MultiExponentiateBoundedExp, [(Self, Uint)]> - for Residue + for ConstMontyForm { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint)], @@ -99,7 +99,7 @@ impl, const LIMBS: usize, const RHS_LIMBS: usize> &bases_and_exponents, exponent_bits, &MOD::MODULUS, - &MOD::R, + &MOD::ONE, MOD::MOD_NEG_INV, ), phantom: core::marker::PhantomData, @@ -110,7 +110,9 @@ impl, const LIMBS: usize, const RHS_LIMBS: usize> #[cfg(test)] mod tests { use crate::traits::MultiExponentiate; - use crate::{const_residue, impl_modulus, modular::residue::ResidueParams, U256}; + use crate::{ + const_monty_form, impl_modulus, modular::const_monty_form::ConstMontyParams, U256, + }; impl_modulus!( Modulus, @@ -121,7 +123,7 @@ mod tests { #[test] fn test_powmod_small_base() { let base = U256::from(105u64); - let base_mod = const_residue!(base, Modulus); + let base_mod = const_monty_form!(base, Modulus); let exponent = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); @@ -137,7 +139,7 @@ mod tests { fn test_powmod_small_exponent() { let base = U256::from_be_hex("3435D18AA8313EBBE4D20002922225B53F75DC4453BB3EEC0378646F79B524A4"); - let base_mod = const_residue!(base, Modulus); + let base_mod = const_monty_form!(base, Modulus); let exponent = U256::from(105u64); @@ -152,7 +154,7 @@ mod tests { fn test_powmod() { let base = U256::from_be_hex("3435D18AA8313EBBE4D20002922225B53F75DC4453BB3EEC0378646F79B524A4"); - let base_mod = const_residue!(base, Modulus); + let base_mod = const_monty_form!(base, Modulus); let exponent = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); @@ -167,11 +169,11 @@ mod tests { #[test] fn test_multi_exp_array() { let base = U256::from(2u8); - let base_mod = const_residue!(base, Modulus); + let base_mod = const_monty_form!(base, Modulus); let exponent = U256::from(33u8); let bases_and_exponents = [(base_mod, exponent)]; - let res = crate::modular::residue::Residue::::multi_exponentiate( + let res = crate::modular::const_monty_form::ConstMontyForm::::multi_exponentiate( &bases_and_exponents, ); @@ -182,14 +184,14 @@ mod tests { let base2 = U256::from_be_hex("3435D18AA8313EBBE4D20002922225B53F75DC4453BB3EEC0378646F79B524A4"); - let base2_mod = const_residue!(base2, Modulus); + let base2_mod = const_monty_form!(base2, Modulus); let exponent2 = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); let expected = base_mod.pow(&exponent) * base2_mod.pow(&exponent2); let bases_and_exponents = [(base_mod, exponent), (base2_mod, exponent2)]; - let res = crate::modular::residue::Residue::::multi_exponentiate( + let res = crate::modular::const_monty_form::ConstMontyForm::::multi_exponentiate( &bases_and_exponents, ); @@ -200,11 +202,11 @@ mod tests { #[test] fn test_multi_exp_slice() { let base = U256::from(2u8); - let base_mod = const_residue!(base, Modulus); + let base_mod = const_monty_form!(base, Modulus); let exponent = U256::from(33u8); let bases_and_exponents = vec![(base_mod, exponent)]; - let res = crate::modular::residue::Residue::::multi_exponentiate( + let res = crate::modular::const_monty_form::ConstMontyForm::::multi_exponentiate( bases_and_exponents.as_slice(), ); @@ -215,14 +217,14 @@ mod tests { let base2 = U256::from_be_hex("3435D18AA8313EBBE4D20002922225B53F75DC4453BB3EEC0378646F79B524A4"); - let base2_mod = const_residue!(base2, Modulus); + let base2_mod = const_monty_form!(base2, Modulus); let exponent2 = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); let expected = base_mod.pow(&exponent) * base2_mod.pow(&exponent2); let bases_and_exponents = vec![(base_mod, exponent), (base2_mod, exponent2)]; - let res = crate::modular::residue::Residue::::multi_exponentiate( + let res = crate::modular::const_monty_form::ConstMontyForm::::multi_exponentiate( bases_and_exponents.as_slice(), ); diff --git a/src/modular/const_monty_form/sub.rs b/src/modular/const_monty_form/sub.rs new file mode 100644 index 000000000..b565bc41d --- /dev/null +++ b/src/modular/const_monty_form/sub.rs @@ -0,0 +1,104 @@ +//! Subtractions between integers in Montgomery form with a constant modulus. + +use super::{ConstMontyForm, ConstMontyParams}; +use crate::modular::sub::sub_montgomery_form; +use core::ops::{Sub, SubAssign}; + +impl, const LIMBS: usize> ConstMontyForm { + /// Subtracts `rhs`. + pub const fn sub(&self, rhs: &Self) -> Self { + Self { + montgomery_form: sub_montgomery_form( + &self.montgomery_form, + &rhs.montgomery_form, + &MOD::MODULUS.0, + ), + phantom: core::marker::PhantomData, + } + } +} + +impl, const LIMBS: usize> Sub<&ConstMontyForm> + for &ConstMontyForm +{ + type Output = ConstMontyForm; + fn sub(self, rhs: &ConstMontyForm) -> ConstMontyForm { + self.sub(rhs) + } +} + +impl, const LIMBS: usize> Sub> + for &ConstMontyForm +{ + type Output = ConstMontyForm; + #[allow(clippy::op_ref)] + fn sub(self, rhs: ConstMontyForm) -> ConstMontyForm { + self - &rhs + } +} + +impl, const LIMBS: usize> Sub<&ConstMontyForm> + for ConstMontyForm +{ + type Output = ConstMontyForm; + #[allow(clippy::op_ref)] + fn sub(self, rhs: &ConstMontyForm) -> ConstMontyForm { + &self - rhs + } +} + +impl, const LIMBS: usize> Sub> + for ConstMontyForm +{ + type Output = ConstMontyForm; + fn sub(self, rhs: ConstMontyForm) -> ConstMontyForm { + &self - &rhs + } +} + +impl, const LIMBS: usize> SubAssign<&Self> + for ConstMontyForm +{ + fn sub_assign(&mut self, rhs: &Self) { + *self = *self - rhs; + } +} + +impl, const LIMBS: usize> SubAssign + for ConstMontyForm +{ + fn sub_assign(&mut self, rhs: Self) { + *self -= &rhs; + } +} + +#[cfg(test)] +mod tests { + use crate::{ + const_monty_form, impl_modulus, modular::const_monty_form::ConstMontyParams, U256, + }; + + impl_modulus!( + Modulus, + U256, + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" + ); + + #[test] + fn sub_overflow() { + let x = + U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); + let mut x_mod = const_monty_form!(x, Modulus); + + let y = + U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); + let y_mod = const_monty_form!(y, Modulus); + + x_mod -= &y_mod; + + let expected = + U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56"); + + assert_eq!(expected, x_mod.retrieve()); + } +} diff --git a/src/modular/dyn_residue/add.rs b/src/modular/dyn_residue/add.rs deleted file mode 100644 index 8b7121e3c..000000000 --- a/src/modular/dyn_residue/add.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Additions between residues with a modulus set at runtime. - -use super::DynResidue; -use crate::modular::add::add_montgomery_form; -use core::ops::{Add, AddAssign}; - -impl DynResidue { - /// Adds `rhs`. - pub const fn add(&self, rhs: &Self) -> Self { - Self { - montgomery_form: add_montgomery_form( - &self.montgomery_form, - &rhs.montgomery_form, - &self.residue_params.modulus, - ), - residue_params: self.residue_params, - } - } -} - -impl Add<&DynResidue> for &DynResidue { - type Output = DynResidue; - fn add(self, rhs: &DynResidue) -> DynResidue { - debug_assert_eq!(self.residue_params, rhs.residue_params); - self.add(rhs) - } -} - -impl Add> for &DynResidue { - type Output = DynResidue; - #[allow(clippy::op_ref)] - fn add(self, rhs: DynResidue) -> DynResidue { - self + &rhs - } -} - -impl Add<&DynResidue> for DynResidue { - type Output = DynResidue; - #[allow(clippy::op_ref)] - fn add(self, rhs: &DynResidue) -> DynResidue { - &self + rhs - } -} - -impl Add> for DynResidue { - type Output = DynResidue; - fn add(self, rhs: DynResidue) -> DynResidue { - &self + &rhs - } -} - -impl AddAssign<&DynResidue> for DynResidue { - fn add_assign(&mut self, rhs: &DynResidue) { - *self = *self + rhs; - } -} - -impl AddAssign> for DynResidue { - fn add_assign(&mut self, rhs: DynResidue) { - *self += &rhs; - } -} - -#[cfg(test)] -mod tests { - use crate::{ - modular::dyn_residue::{DynResidue, DynResidueParams}, - U256, - }; - - #[test] - fn add_overflow() { - let params = DynResidueParams::new(&U256::from_be_hex( - "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", - )) - .unwrap(); - - let x = - U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); - let mut x_mod = DynResidue::new(&x, params); - - let y = - U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); - let y_mod = DynResidue::new(&y, params); - - x_mod += &y_mod; - - let expected = - U256::from_be_hex("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956"); - - assert_eq!(expected, x_mod.retrieve()); - } -} diff --git a/src/modular/dyn_residue/mul.rs b/src/modular/dyn_residue/mul.rs deleted file mode 100644 index f9895ff14..000000000 --- a/src/modular/dyn_residue/mul.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! Multiplications between residues with a modulus set at runtime. - -use super::DynResidue; -use crate::{ - modular::mul::{mul_montgomery_form, square_montgomery_form}, - traits::Square, -}; -use core::ops::{Mul, MulAssign}; - -impl DynResidue { - /// Multiplies by `rhs`. - pub const fn mul(&self, rhs: &Self) -> Self { - Self { - montgomery_form: mul_montgomery_form( - &self.montgomery_form, - &rhs.montgomery_form, - &self.residue_params.modulus, - self.residue_params.mod_neg_inv, - ), - residue_params: self.residue_params, - } - } - - /// Computes the (reduced) square of a residue. - pub const fn square(&self) -> Self { - Self { - montgomery_form: square_montgomery_form( - &self.montgomery_form, - &self.residue_params.modulus, - self.residue_params.mod_neg_inv, - ), - residue_params: self.residue_params, - } - } -} - -impl Mul<&DynResidue> for &DynResidue { - type Output = DynResidue; - fn mul(self, rhs: &DynResidue) -> DynResidue { - debug_assert_eq!(self.residue_params, rhs.residue_params); - self.mul(rhs) - } -} - -impl Mul> for &DynResidue { - type Output = DynResidue; - #[allow(clippy::op_ref)] - fn mul(self, rhs: DynResidue) -> DynResidue { - self * &rhs - } -} - -impl Mul<&DynResidue> for DynResidue { - type Output = DynResidue; - #[allow(clippy::op_ref)] - fn mul(self, rhs: &DynResidue) -> DynResidue { - &self * rhs - } -} - -impl Mul> for DynResidue { - type Output = DynResidue; - fn mul(self, rhs: DynResidue) -> DynResidue { - &self * &rhs - } -} - -impl MulAssign<&DynResidue> for DynResidue { - fn mul_assign(&mut self, rhs: &DynResidue) { - *self = *self * rhs; - } -} - -impl MulAssign> for DynResidue { - fn mul_assign(&mut self, rhs: DynResidue) { - *self *= &rhs; - } -} - -impl Square for DynResidue { - fn square(&self) -> Self { - DynResidue::square(self) - } -} diff --git a/src/modular/dyn_residue/neg.rs b/src/modular/dyn_residue/neg.rs deleted file mode 100644 index 0bab51e2e..000000000 --- a/src/modular/dyn_residue/neg.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Negations of residues with a modulus set at runtime. - -use super::DynResidue; -use core::ops::Neg; - -impl DynResidue { - /// Negates the number. - pub const fn neg(&self) -> Self { - Self::zero(self.residue_params).sub(self) - } -} - -impl Neg for DynResidue { - type Output = Self; - fn neg(self) -> Self { - DynResidue::neg(&self) - } -} - -impl Neg for &DynResidue { - type Output = DynResidue; - fn neg(self) -> DynResidue { - DynResidue::neg(self) - } -} diff --git a/src/modular/dyn_residue/sub.rs b/src/modular/dyn_residue/sub.rs deleted file mode 100644 index 6bab383a8..000000000 --- a/src/modular/dyn_residue/sub.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Subtractions between residues with a modulus set at runtime. - -use super::DynResidue; -use crate::modular::sub::sub_montgomery_form; -use core::ops::{Sub, SubAssign}; - -impl DynResidue { - /// Subtracts `rhs`. - pub const fn sub(&self, rhs: &Self) -> Self { - Self { - montgomery_form: sub_montgomery_form( - &self.montgomery_form, - &rhs.montgomery_form, - &self.residue_params.modulus, - ), - residue_params: self.residue_params, - } - } -} - -impl Sub<&DynResidue> for &DynResidue { - type Output = DynResidue; - fn sub(self, rhs: &DynResidue) -> DynResidue { - debug_assert_eq!(self.residue_params, rhs.residue_params); - self.sub(rhs) - } -} - -impl Sub> for &DynResidue { - type Output = DynResidue; - #[allow(clippy::op_ref)] - fn sub(self, rhs: DynResidue) -> DynResidue { - self - &rhs - } -} - -impl Sub<&DynResidue> for DynResidue { - type Output = DynResidue; - #[allow(clippy::op_ref)] - fn sub(self, rhs: &DynResidue) -> DynResidue { - &self - rhs - } -} - -impl Sub> for DynResidue { - type Output = DynResidue; - fn sub(self, rhs: DynResidue) -> DynResidue { - &self - &rhs - } -} - -impl SubAssign<&DynResidue> for DynResidue { - fn sub_assign(&mut self, rhs: &DynResidue) { - *self = *self - rhs; - } -} - -impl SubAssign> for DynResidue { - fn sub_assign(&mut self, rhs: DynResidue) { - *self -= &rhs; - } -} - -#[cfg(test)] -mod tests { - use crate::{ - modular::dyn_residue::{DynResidue, DynResidueParams}, - U256, - }; - - #[test] - fn sub_overflow() { - let params = DynResidueParams::new(&U256::from_be_hex( - "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", - )) - .unwrap(); - - let x = - U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); - let mut x_mod = DynResidue::new(&x, params); - - let y = - U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); - let y_mod = DynResidue::new(&y, params); - - x_mod -= &y_mod; - - let expected = - U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56"); - - assert_eq!(expected, x_mod.retrieve()); - } -} diff --git a/src/modular/dyn_residue.rs b/src/modular/monty_form.rs similarity index 54% rename from src/modular/dyn_residue.rs rename to src/modular/monty_form.rs index 706cf7339..e2c7ba58f 100644 --- a/src/modular/dyn_residue.rs +++ b/src/modular/monty_form.rs @@ -1,4 +1,4 @@ -//! Implements `DynResidue`s, supporting modular arithmetic with a modulus set at runtime. +//! Implements `MontyForm`s, supporting modular arithmetic with a modulus set at runtime. mod add; pub(super) mod inv; @@ -8,9 +8,9 @@ mod pow; mod sub; use super::{ + const_monty_form::{ConstMontyForm, ConstMontyParams}, div_by_2::div_by_2, reduction::montgomery_reduction, - residue::{Residue, ResidueParams}, Retrieve, }; use crate::{Limb, NonZero, Uint, Word, Zero}; @@ -18,22 +18,22 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; /// Parameters to efficiently go to/from the Montgomery form for an odd modulus provided at runtime. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct DynResidueParams { +pub struct MontyParams { /// The constant modulus modulus: Uint, - /// Parameter used in Montgomery reduction - r: Uint, - /// R^2, used to move into Montgomery form + /// 1 in Montgomery form (a.k.a. `R`) + one: Uint, + /// `R^2 mod modulus`, used to move into Montgomery form r2: Uint, - /// R^3, used to compute the multiplicative inverse + /// `R^3 mod modulus`, used to compute the multiplicative inverse r3: Uint, /// The lowest limbs of -(MODULUS^-1) mod R /// We only need the LSB because during reduction this value is multiplied modulo 2**Limb::BITS. mod_neg_inv: Limb, } -impl DynResidueParams { - /// Instantiates a new set of `ResidueParams` representing the given `modulus` if it is odd. +impl MontyParams { + /// Instantiates a new set of `MontyParams` representing the given `modulus` if it is odd. /// /// Returns `None` if the provided modulus is not odd. pub fn new(modulus: &Uint) -> CtOption { @@ -47,19 +47,24 @@ impl DynResidueParams { )) .expect("modulus ensured non-zero"); - let r = Uint::MAX.rem_vartime(&nz_modulus).wrapping_add(&Uint::ONE); - let r2 = Uint::rem_wide_vartime(r.square_wide(), &nz_modulus); + // `R mod modulus` where `R = 2^BITS`. + // Represents 1 in Montgomery form. + let one = Uint::MAX.rem_vartime(&nz_modulus).wrapping_add(&Uint::ONE); + + // `R^2 mod modulus`, used to convert integers to Montgomery form. + let r2 = Uint::rem_wide_vartime(one.square_wide(), &nz_modulus); let maybe_inverse = modulus.inv_mod2k_vartime(Word::BITS); // If the inverse exists, it means the modulus is odd. let (inv_mod_limb, modulus_is_odd) = maybe_inverse.components_ref(); let mod_neg_inv = Limb(Word::MIN.wrapping_sub(inv_mod_limb.limbs[0].0)); + // `R^3 mod modulus`, used for inversion in Montgomery form. let r3 = montgomery_reduction(&r2.square_wide(), modulus, mod_neg_inv); let params = Self { modulus: *modulus, - r, + one, r2, r3, mod_neg_inv, @@ -73,14 +78,14 @@ impl DynResidueParams { &self.modulus } - /// Create `DynResidueParams` corresponding to a `ResidueParams`. - pub const fn from_residue_params

() -> Self + /// Create `MontyParams` corresponding to a `ConstMontyParams`. + pub const fn from_const_params

() -> Self where - P: ResidueParams, + P: ConstMontyParams, { Self { modulus: P::MODULUS.0, - r: P::R, + one: P::ONE, r2: P::R2, r3: P::R3, mod_neg_inv: P::MOD_NEG_INV, @@ -88,11 +93,11 @@ impl DynResidueParams { } } -impl ConditionallySelectable for DynResidueParams { +impl ConditionallySelectable for MontyParams { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { Self { modulus: Uint::conditional_select(&a.modulus, &b.modulus, choice), - r: Uint::conditional_select(&a.r, &b.r, choice), + one: Uint::conditional_select(&a.one, &b.one, choice), r2: Uint::conditional_select(&a.r2, &b.r2, choice), r3: Uint::conditional_select(&a.r3, &b.r3, choice), mod_neg_inv: Limb::conditional_select(&a.mod_neg_inv, &b.mod_neg_inv, choice), @@ -100,91 +105,85 @@ impl ConditionallySelectable for DynResidueParams { } } -impl ConstantTimeEq for DynResidueParams { +impl ConstantTimeEq for MontyParams { fn ct_eq(&self, other: &Self) -> Choice { self.modulus.ct_eq(&other.modulus) - & self.r.ct_eq(&other.r) + & self.one.ct_eq(&other.one) & self.r2.ct_eq(&other.r2) & self.r3.ct_eq(&other.r3) & self.mod_neg_inv.ct_eq(&other.mod_neg_inv) } } -/// A residue represented using `LIMBS` limbs. The odd modulus of this residue is set at runtime. +/// An integer in Montgomery form represented using `LIMBS` limbs. +/// The odd modulus is set at runtime. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct DynResidue { +pub struct MontyForm { montgomery_form: Uint, - residue_params: DynResidueParams, + params: MontyParams, } -impl DynResidue { - /// Instantiates a new `Residue` that represents this `integer` mod `MOD`. - pub const fn new(integer: &Uint, residue_params: DynResidueParams) -> Self { - let product = integer.split_mul(&residue_params.r2); - let montgomery_form = montgomery_reduction( - &product, - &residue_params.modulus, - residue_params.mod_neg_inv, - ); +impl MontyForm { + /// Instantiates a new `MontyForm` that represents this `integer` mod `MOD`. + pub const fn new(integer: &Uint, params: MontyParams) -> Self { + let product = integer.split_mul(¶ms.r2); + let montgomery_form = montgomery_reduction(&product, ¶ms.modulus, params.mod_neg_inv); Self { montgomery_form, - residue_params, + params, } } - /// Retrieves the integer currently encoded in this `Residue`, guaranteed to be reduced. + /// Retrieves the integer currently encoded in this `MontyForm`, guaranteed to be reduced. pub const fn retrieve(&self) -> Uint { montgomery_reduction( &(self.montgomery_form, Uint::ZERO), - &self.residue_params.modulus, - self.residue_params.mod_neg_inv, + &self.params.modulus, + self.params.mod_neg_inv, ) } - /// Instantiates a new `Residue` that represents zero. - pub const fn zero(residue_params: DynResidueParams) -> Self { + /// Instantiates a new `MontyForm` that represents zero. + pub const fn zero(params: MontyParams) -> Self { Self { montgomery_form: Uint::::ZERO, - residue_params, + params, } } - /// Instantiates a new `Residue` that represents 1. - pub const fn one(residue_params: DynResidueParams) -> Self { + /// Instantiates a new `MontyForm` that represents 1. + pub const fn one(params: MontyParams) -> Self { Self { - montgomery_form: residue_params.r, - residue_params, + montgomery_form: params.one, + params, } } - /// Returns the parameter struct used to initialize this residue. - pub const fn params(&self) -> &DynResidueParams { - &self.residue_params + /// Returns the parameter struct used to initialize this object. + pub const fn params(&self) -> &MontyParams { + &self.params } - /// Access the `DynResidue` value in Montgomery form. + /// Access the `MontyForm` value in Montgomery form. pub const fn as_montgomery(&self) -> &Uint { &self.montgomery_form } - /// Mutably access the `DynResidue` value in Montgomery form. + /// Mutably access the `MontyForm` value in Montgomery form. pub fn as_montgomery_mut(&mut self) -> &mut Uint { &mut self.montgomery_form } - /// Create a `DynResidue` from a value in Montgomery form. - pub const fn from_montgomery( - integer: Uint, - residue_params: DynResidueParams, - ) -> Self { + /// Create a `MontyForm` from a value in Montgomery form. + pub const fn from_montgomery(integer: Uint, params: MontyParams) -> Self { Self { montgomery_form: integer, - residue_params, + params, } } - /// Extract the value from the `DynResidue` in Montgomery form. + /// Extract the value from the `MontyForm` in Montgomery form. pub const fn to_montgomery(&self) -> Uint { self.montgomery_form } @@ -196,29 +195,31 @@ impl DynResidue { /// (since the modulus `p` in Montgomery form is always odd, this divides entirely). pub fn div_by_2(&self) -> Self { Self { - montgomery_form: div_by_2(&self.montgomery_form, &self.residue_params.modulus), - residue_params: self.residue_params, + montgomery_form: div_by_2(&self.montgomery_form, &self.params.modulus), + params: self.params, } } } -impl Retrieve for DynResidue { +impl Retrieve for MontyForm { type Output = Uint; fn retrieve(&self) -> Self::Output { self.retrieve() } } -impl> From<&Residue> for DynResidue { - fn from(residue: &Residue) -> Self { +impl> From<&ConstMontyForm> + for MontyForm +{ + fn from(const_monty_form: &ConstMontyForm) -> Self { Self { - montgomery_form: residue.to_montgomery(), - residue_params: DynResidueParams::from_residue_params::

(), + montgomery_form: const_monty_form.to_montgomery(), + params: MontyParams::from_const_params::

(), } } } -impl ConditionallySelectable for DynResidue { +impl ConditionallySelectable for MontyForm { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { Self { montgomery_form: Uint::conditional_select( @@ -226,25 +227,20 @@ impl ConditionallySelectable for DynResidue { &b.montgomery_form, choice, ), - residue_params: DynResidueParams::conditional_select( - &a.residue_params, - &b.residue_params, - choice, - ), + params: MontyParams::conditional_select(&a.params, &b.params, choice), } } } -impl ConstantTimeEq for DynResidue { +impl ConstantTimeEq for MontyForm { fn ct_eq(&self, other: &Self) -> Choice { - self.montgomery_form.ct_eq(&other.montgomery_form) - & self.residue_params.ct_eq(&other.residue_params) + self.montgomery_form.ct_eq(&other.montgomery_form) & self.params.ct_eq(&other.params) } } /// NOTE: this does _not_ zeroize the parameters, in order to maintain some form of type consistency #[cfg(feature = "zeroize")] -impl zeroize::Zeroize for DynResidue { +impl zeroize::Zeroize for MontyForm { fn zeroize(&mut self) { self.montgomery_form.zeroize() } @@ -257,17 +253,17 @@ mod test { const LIMBS: usize = nlimbs!(64); #[test] - // Test that a valid modulus yields `DynResidueParams` + // Test that a valid modulus yields `MontyParams` fn test_valid_modulus() { let valid_modulus = Uint::::from(3u8); - DynResidueParams::::new(&valid_modulus).unwrap(); + MontyParams::::new(&valid_modulus).unwrap(); } #[test] - // Test that an invalid checked modulus does not yield `DynResidueParams` + // Test that an invalid checked modulus does not yield `MontyParams` fn test_invalid_checked_modulus() { assert!(bool::from( - DynResidueParams::::new(&Uint::from(2u8)).is_none() + MontyParams::::new(&Uint::from(2u8)).is_none() )) } } diff --git a/src/modular/monty_form/add.rs b/src/modular/monty_form/add.rs new file mode 100644 index 000000000..097c89a33 --- /dev/null +++ b/src/modular/monty_form/add.rs @@ -0,0 +1,93 @@ +//! Additions between integers in Montgomery form with a modulus set at runtime. + +use super::MontyForm; +use crate::modular::add::add_montgomery_form; +use core::ops::{Add, AddAssign}; + +impl MontyForm { + /// Adds `rhs`. + pub const fn add(&self, rhs: &Self) -> Self { + Self { + montgomery_form: add_montgomery_form( + &self.montgomery_form, + &rhs.montgomery_form, + &self.params.modulus, + ), + params: self.params, + } + } +} + +impl Add<&MontyForm> for &MontyForm { + type Output = MontyForm; + fn add(self, rhs: &MontyForm) -> MontyForm { + debug_assert_eq!(self.params, rhs.params); + self.add(rhs) + } +} + +impl Add> for &MontyForm { + type Output = MontyForm; + #[allow(clippy::op_ref)] + fn add(self, rhs: MontyForm) -> MontyForm { + self + &rhs + } +} + +impl Add<&MontyForm> for MontyForm { + type Output = MontyForm; + #[allow(clippy::op_ref)] + fn add(self, rhs: &MontyForm) -> MontyForm { + &self + rhs + } +} + +impl Add> for MontyForm { + type Output = MontyForm; + fn add(self, rhs: MontyForm) -> MontyForm { + &self + &rhs + } +} + +impl AddAssign<&MontyForm> for MontyForm { + fn add_assign(&mut self, rhs: &MontyForm) { + *self = *self + rhs; + } +} + +impl AddAssign> for MontyForm { + fn add_assign(&mut self, rhs: MontyForm) { + *self += &rhs; + } +} + +#[cfg(test)] +mod tests { + use crate::{ + modular::monty_form::{MontyForm, MontyParams}, + U256, + }; + + #[test] + fn add_overflow() { + let params = MontyParams::new(&U256::from_be_hex( + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + )) + .unwrap(); + + let x = + U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); + let mut x_mod = MontyForm::new(&x, params); + + let y = + U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); + let y_mod = MontyForm::new(&y, params); + + x_mod += &y_mod; + + let expected = + U256::from_be_hex("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956"); + + assert_eq!(expected, x_mod.retrieve()); + } +} diff --git a/src/modular/dyn_residue/inv.rs b/src/modular/monty_form/inv.rs similarity index 65% rename from src/modular/dyn_residue/inv.rs rename to src/modular/monty_form/inv.rs index f5f0ab617..f1743a520 100644 --- a/src/modular/dyn_residue/inv.rs +++ b/src/modular/monty_form/inv.rs @@ -1,6 +1,6 @@ -//! Multiplicative inverses of residues with a modulus set at runtime. +//! Multiplicative inverses of integers in Montgomery form with a modulus set at runtime. -use super::{DynResidue, DynResidueParams}; +use super::{MontyForm, MontyParams}; use crate::{ modular::BernsteinYangInverter, traits::Invert, ConstCtOption, Inverter, PrecomputeInverter, PrecomputeInverterWithAdjuster, Uint, @@ -8,21 +8,21 @@ use crate::{ use core::fmt; use subtle::CtOption; -impl DynResidue +impl MontyForm where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, Output = Uint, >, { - /// Computes the residue `self^-1` representing the multiplicative inverse of `self`. + /// 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). pub const fn inv(&self) -> ConstCtOption { let inverter = as PrecomputeInverter>::Inverter::new( - &self.residue_params.modulus, - &self.residue_params.r2, + &self.params.modulus, + &self.params.r2, ) .expect("modulus should be valid"); @@ -31,14 +31,14 @@ where let ret = Self { montgomery_form: *inverse, - residue_params: self.residue_params, + params: self.params, }; ConstCtOption::new(ret, inverse_is_some) } } -impl Invert for DynResidue +impl Invert for MontyForm where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, @@ -52,49 +52,49 @@ where } } -impl PrecomputeInverter for DynResidueParams +impl PrecomputeInverter for MontyParams where Uint: PrecomputeInverter> + PrecomputeInverterWithAdjuster, { - type Inverter = DynResidueInverter; - type Output = DynResidue; + type Inverter = MontyFormInverter; + type Output = MontyForm; - fn precompute_inverter(&self) -> DynResidueInverter { - DynResidueInverter { + fn precompute_inverter(&self) -> MontyFormInverter { + MontyFormInverter { inverter: self.modulus.precompute_inverter_with_adjuster(&self.r2), - residue_params: *self, + params: *self, } } } -/// Bernstein-Yang inverter which inverts [`DynResidue`] types. -pub struct DynResidueInverter +/// Bernstein-Yang inverter which inverts [`MontyForm`] types. +pub struct MontyFormInverter where Uint: PrecomputeInverter>, { inverter: as PrecomputeInverter>::Inverter, - residue_params: DynResidueParams, + params: MontyParams, } -impl Inverter for DynResidueInverter +impl Inverter for MontyFormInverter where Uint: PrecomputeInverter>, { - type Output = DynResidue; + type Output = MontyForm; - fn invert(&self, value: &DynResidue) -> CtOption { - debug_assert_eq!(self.residue_params, value.residue_params); + fn invert(&self, value: &MontyForm) -> CtOption { + debug_assert_eq!(self.params, value.params); self.inverter .invert(&value.montgomery_form) - .map(|montgomery_form| DynResidue { + .map(|montgomery_form| MontyForm { montgomery_form, - residue_params: value.residue_params, + params: value.params, }) } } -impl fmt::Debug for DynResidueInverter +impl fmt::Debug for MontyFormInverter where Uint: PrecomputeInverter< Inverter = BernsteinYangInverter, @@ -102,7 +102,7 @@ where >, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DynResidueInverter") + f.debug_struct("MontyFormInverter") .field("modulus", &self.inverter.modulus) .finish() } @@ -110,11 +110,11 @@ where #[cfg(test)] mod tests { - use super::{DynResidue, DynResidueParams}; + use super::{MontyForm, MontyParams}; use crate::{Invert, Inverter, PrecomputeInverter, U256}; - fn residue_params() -> DynResidueParams<{ U256::LIMBS }> { - DynResidueParams::new(&U256::from_be_hex( + fn params() -> MontyParams<{ U256::LIMBS }> { + MontyParams::new(&U256::from_be_hex( "15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409", )) .unwrap() @@ -122,10 +122,10 @@ mod tests { #[test] fn test_self_inverse() { - let params = residue_params(); + let params = params(); let x = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); - let x_mod = DynResidue::new(&x, params); + let x_mod = MontyForm::new(&x, params); let inv = x_mod.invert().unwrap(); let res = x_mod * inv; @@ -135,10 +135,10 @@ mod tests { #[test] fn test_self_inverse_precomuted() { - let params = residue_params(); + let params = params(); let x = U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); - let x_mod = DynResidue::new(&x, params); + let x_mod = MontyForm::new(&x, params); let inverter = params.precompute_inverter(); let inv = inverter.invert(&x_mod).unwrap(); diff --git a/src/modular/monty_form/mul.rs b/src/modular/monty_form/mul.rs new file mode 100644 index 000000000..7026c8fef --- /dev/null +++ b/src/modular/monty_form/mul.rs @@ -0,0 +1,84 @@ +//! Multiplications between integers in Montgomery form with a modulus set at runtime. + +use super::MontyForm; +use crate::{ + modular::mul::{mul_montgomery_form, square_montgomery_form}, + traits::Square, +}; +use core::ops::{Mul, MulAssign}; + +impl MontyForm { + /// Multiplies by `rhs`. + pub const fn mul(&self, rhs: &Self) -> Self { + Self { + montgomery_form: mul_montgomery_form( + &self.montgomery_form, + &rhs.montgomery_form, + &self.params.modulus, + self.params.mod_neg_inv, + ), + params: self.params, + } + } + + /// Computes the (reduced) square. + pub const fn square(&self) -> Self { + Self { + montgomery_form: square_montgomery_form( + &self.montgomery_form, + &self.params.modulus, + self.params.mod_neg_inv, + ), + params: self.params, + } + } +} + +impl Mul<&MontyForm> for &MontyForm { + type Output = MontyForm; + fn mul(self, rhs: &MontyForm) -> MontyForm { + debug_assert_eq!(self.params, rhs.params); + self.mul(rhs) + } +} + +impl Mul> for &MontyForm { + type Output = MontyForm; + #[allow(clippy::op_ref)] + fn mul(self, rhs: MontyForm) -> MontyForm { + self * &rhs + } +} + +impl Mul<&MontyForm> for MontyForm { + type Output = MontyForm; + #[allow(clippy::op_ref)] + fn mul(self, rhs: &MontyForm) -> MontyForm { + &self * rhs + } +} + +impl Mul> for MontyForm { + type Output = MontyForm; + fn mul(self, rhs: MontyForm) -> MontyForm { + &self * &rhs + } +} + +impl MulAssign<&MontyForm> for MontyForm { + fn mul_assign(&mut self, rhs: &MontyForm) { + *self = *self * rhs; + } +} + +impl MulAssign> for MontyForm { + fn mul_assign(&mut self, rhs: MontyForm) { + *self *= &rhs; + } +} + +impl Square for MontyForm { + fn square(&self) -> Self { + MontyForm::square(self) + } +} diff --git a/src/modular/monty_form/neg.rs b/src/modular/monty_form/neg.rs new file mode 100644 index 000000000..3792ee3a8 --- /dev/null +++ b/src/modular/monty_form/neg.rs @@ -0,0 +1,25 @@ +//! Negations of integers in Montgomery form with a modulus set at runtime. + +use super::MontyForm; +use core::ops::Neg; + +impl MontyForm { + /// Negates the number. + pub const fn neg(&self) -> Self { + Self::zero(self.params).sub(self) + } +} + +impl Neg for MontyForm { + type Output = Self; + fn neg(self) -> Self { + MontyForm::neg(&self) + } +} + +impl Neg for &MontyForm { + type Output = MontyForm; + fn neg(self) -> MontyForm { + MontyForm::neg(self) + } +} diff --git a/src/modular/dyn_residue/pow.rs b/src/modular/monty_form/pow.rs similarity index 77% rename from src/modular/dyn_residue/pow.rs rename to src/modular/monty_form/pow.rs index 5749e4a08..f7a8943fd 100644 --- a/src/modular/dyn_residue/pow.rs +++ b/src/modular/monty_form/pow.rs @@ -1,6 +1,6 @@ -//! Exponentiation of residues with a modulus set at runtime. +//! Exponentiation of integers in Montgomery form with a modulus set at runtime. -use super::DynResidue; +use super::MontyForm; use crate::{ modular::pow::{multi_exponentiate_montgomery_form_array, pow_montgomery_form}, MultiExponentiateBoundedExp, PowBoundedExp, Uint, @@ -9,12 +9,12 @@ use crate::{ #[cfg(feature = "alloc")] use {crate::modular::pow::multi_exponentiate_montgomery_form_slice, alloc::vec::Vec}; -impl DynResidue { +impl MontyForm { /// Raises to the `exponent` power. pub const fn pow( &self, exponent: &Uint, - ) -> DynResidue { + ) -> MontyForm { self.pow_bounded_exp(exponent, Uint::::BITS) } @@ -33,17 +33,17 @@ impl DynResidue { &self.montgomery_form, exponent, exponent_bits, - &self.residue_params.modulus, - &self.residue_params.r, - self.residue_params.mod_neg_inv, + &self.params.modulus, + &self.params.one, + self.params.mod_neg_inv, ), - residue_params: self.residue_params, + params: self.params, } } } impl PowBoundedExp> - for DynResidue + for MontyForm { fn pow_bounded_exp(&self, exponent: &Uint, exponent_bits: u32) -> Self { self.pow_bounded_exp(exponent, exponent_bits) @@ -52,14 +52,14 @@ impl PowBoundedExp> impl MultiExponentiateBoundedExp, [(Self, Uint); N]> - for DynResidue + for MontyForm { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint); N], exponent_bits: u32, ) -> Self { const_assert_ne!(N, 0, "bases_and_exponents must not be empty"); - let residue_params = bases_and_exponents[0].0.residue_params; + let params = bases_and_exponents[0].0.params; let mut bases_and_exponents_montgomery_form = [(Uint::::ZERO, Uint::::ZERO); N]; @@ -75,18 +75,18 @@ impl montgomery_form: multi_exponentiate_montgomery_form_array( &bases_and_exponents_montgomery_form, exponent_bits, - &residue_params.modulus, - &residue_params.r, - residue_params.mod_neg_inv, + ¶ms.modulus, + ¶ms.one, + params.mod_neg_inv, ), - residue_params, + params, } } } #[cfg(feature = "alloc")] impl - MultiExponentiateBoundedExp, [(Self, Uint)]> for DynResidue + MultiExponentiateBoundedExp, [(Self, Uint)]> for MontyForm { fn multi_exponentiate_bounded_exp( bases_and_exponents: &[(Self, Uint)], @@ -96,7 +96,7 @@ impl !bases_and_exponents.is_empty(), "bases_and_exponents must not be empty" ); - let residue_params = bases_and_exponents[0].0.residue_params; + let params = bases_and_exponents[0].0.params; let bases_and_exponents: Vec<(Uint, Uint)> = bases_and_exponents .iter() @@ -106,11 +106,11 @@ impl montgomery_form: multi_exponentiate_montgomery_form_slice( &bases_and_exponents, exponent_bits, - &residue_params.modulus, - &residue_params.r, - residue_params.mod_neg_inv, + ¶ms.modulus, + ¶ms.one, + params.mod_neg_inv, ), - residue_params, + params, } } } diff --git a/src/modular/monty_form/sub.rs b/src/modular/monty_form/sub.rs new file mode 100644 index 000000000..df6b40f55 --- /dev/null +++ b/src/modular/monty_form/sub.rs @@ -0,0 +1,93 @@ +//! Subtractions between integers in Montgomery form with a modulus set at runtime. + +use super::MontyForm; +use crate::modular::sub::sub_montgomery_form; +use core::ops::{Sub, SubAssign}; + +impl MontyForm { + /// Subtracts `rhs`. + pub const fn sub(&self, rhs: &Self) -> Self { + Self { + montgomery_form: sub_montgomery_form( + &self.montgomery_form, + &rhs.montgomery_form, + &self.params.modulus, + ), + params: self.params, + } + } +} + +impl Sub<&MontyForm> for &MontyForm { + type Output = MontyForm; + fn sub(self, rhs: &MontyForm) -> MontyForm { + debug_assert_eq!(self.params, rhs.params); + self.sub(rhs) + } +} + +impl Sub> for &MontyForm { + type Output = MontyForm; + #[allow(clippy::op_ref)] + fn sub(self, rhs: MontyForm) -> MontyForm { + self - &rhs + } +} + +impl Sub<&MontyForm> for MontyForm { + type Output = MontyForm; + #[allow(clippy::op_ref)] + fn sub(self, rhs: &MontyForm) -> MontyForm { + &self - rhs + } +} + +impl Sub> for MontyForm { + type Output = MontyForm; + fn sub(self, rhs: MontyForm) -> MontyForm { + &self - &rhs + } +} + +impl SubAssign<&MontyForm> for MontyForm { + fn sub_assign(&mut self, rhs: &MontyForm) { + *self = *self - rhs; + } +} + +impl SubAssign> for MontyForm { + fn sub_assign(&mut self, rhs: MontyForm) { + *self -= &rhs; + } +} + +#[cfg(test)] +mod tests { + use crate::{ + modular::monty_form::{MontyForm, MontyParams}, + U256, + }; + + #[test] + fn sub_overflow() { + let params = MontyParams::new(&U256::from_be_hex( + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + )) + .unwrap(); + + let x = + U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); + let mut x_mod = MontyForm::new(&x, params); + + let y = + U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); + let y_mod = MontyForm::new(&y, params); + + x_mod -= &y_mod; + + let expected = + U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56"); + + assert_eq!(expected, x_mod.retrieve()); + } +} diff --git a/src/modular/pow.rs b/src/modular/pow.rs index b750c4e0f..a29cd1fb7 100644 --- a/src/modular/pow.rs +++ b/src/modular/pow.rs @@ -17,14 +17,14 @@ pub const fn pow_montgomery_form( exponent: &Uint, exponent_bits: u32, modulus: &Uint, - r: &Uint, + one: &Uint, mod_neg_inv: Limb, ) -> Uint { multi_exponentiate_montgomery_form_array( &[(*x, *exponent)], exponent_bits, modulus, - r, + one, mod_neg_inv, ) } @@ -37,11 +37,11 @@ pub const fn multi_exponentiate_montgomery_form_array< bases_and_exponents: &[(Uint, Uint); N], exponent_bits: u32, modulus: &Uint, - r: &Uint, + one: &Uint, mod_neg_inv: Limb, ) -> Uint { if exponent_bits == 0 { - return *r; // 1 in Montgomery form + return *one; // 1 in Montgomery form } let mut powers_and_exponents = @@ -50,7 +50,7 @@ pub const fn multi_exponentiate_montgomery_form_array< let mut i = 0; while i < N { let (base, exponent) = bases_and_exponents[i]; - powers_and_exponents[i] = (compute_powers(&base, modulus, r, mod_neg_inv), exponent); + powers_and_exponents[i] = (compute_powers(&base, modulus, one, mod_neg_inv), exponent); i += 1; } @@ -58,7 +58,7 @@ pub const fn multi_exponentiate_montgomery_form_array< &powers_and_exponents, exponent_bits, modulus, - r, + one, mod_neg_inv, ) } @@ -74,24 +74,24 @@ pub fn multi_exponentiate_montgomery_form_slice, Uint)], exponent_bits: u32, modulus: &Uint, - r: &Uint, + one: &Uint, mod_neg_inv: Limb, ) -> Uint { if exponent_bits == 0 { - return *r; // 1 in Montgomery form + return *one; // 1 in Montgomery form } let powers_and_exponents: Vec<([Uint; 1 << WINDOW], Uint)> = bases_and_exponents .iter() - .map(|(base, exponent)| (compute_powers(base, modulus, r, mod_neg_inv), *exponent)) + .map(|(base, exponent)| (compute_powers(base, modulus, one, mod_neg_inv), *exponent)) .collect(); multi_exponentiate_montgomery_form_internal( powers_and_exponents.as_slice(), exponent_bits, modulus, - r, + one, mod_neg_inv, ) } @@ -99,11 +99,11 @@ pub fn multi_exponentiate_montgomery_form_slice( x: &Uint, modulus: &Uint, - r: &Uint, + one: &Uint, mod_neg_inv: Limb, ) -> [Uint; 1 << WINDOW] { // powers[i] contains x^i - let mut powers = [*r; 1 << WINDOW]; + let mut powers = [*one; 1 << WINDOW]; powers[1] = *x; let mut i = 2; @@ -119,7 +119,7 @@ const fn multi_exponentiate_montgomery_form_internal; 1 << WINDOW], Uint)], exponent_bits: u32, modulus: &Uint, - r: &Uint, + one: &Uint, mod_neg_inv: Limb, ) -> Uint { let starting_limb = ((exponent_bits - 1) / Limb::BITS) as usize; @@ -127,7 +127,7 @@ const fn multi_exponentiate_montgomery_form_internal 0 { diff --git a/src/modular/residue/add.rs b/src/modular/residue/add.rs deleted file mode 100644 index f56039f2a..000000000 --- a/src/modular/residue/add.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! Additions between residues with a constant modulus. - -use super::{Residue, ResidueParams}; -use crate::modular::add::add_montgomery_form; -use core::ops::{Add, AddAssign}; - -impl, const LIMBS: usize> Residue { - /// Adds `rhs`. - pub const fn add(&self, rhs: &Residue) -> Self { - Self { - montgomery_form: add_montgomery_form( - &self.montgomery_form, - &rhs.montgomery_form, - &MOD::MODULUS.0, - ), - phantom: core::marker::PhantomData, - } - } -} - -impl, const LIMBS: usize> Add<&Residue> - for &Residue -{ - type Output = Residue; - fn add(self, rhs: &Residue) -> Residue { - self.add(rhs) - } -} - -impl, const LIMBS: usize> Add> - for &Residue -{ - type Output = Residue; - #[allow(clippy::op_ref)] - fn add(self, rhs: Residue) -> Residue { - self + &rhs - } -} - -impl, const LIMBS: usize> Add<&Residue> - for Residue -{ - type Output = Residue; - #[allow(clippy::op_ref)] - fn add(self, rhs: &Residue) -> Residue { - &self + rhs - } -} - -impl, const LIMBS: usize> Add> - for Residue -{ - type Output = Residue; - fn add(self, rhs: Residue) -> Residue { - &self + &rhs - } -} - -impl, const LIMBS: usize> AddAssign<&Self> for Residue { - fn add_assign(&mut self, rhs: &Self) { - *self = *self + rhs; - } -} - -impl, const LIMBS: usize> AddAssign for Residue { - fn add_assign(&mut self, rhs: Self) { - *self += &rhs; - } -} - -#[cfg(test)] -mod tests { - use crate::{const_residue, impl_modulus, modular::residue::ResidueParams, U256}; - - impl_modulus!( - Modulus, - U256, - "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" - ); - - #[test] - fn add_overflow() { - let x = - U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); - let mut x_mod = const_residue!(x, Modulus); - - let y = - U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); - let y_mod = const_residue!(y, Modulus); - - x_mod += &y_mod; - - let expected = - U256::from_be_hex("1a2472fde50286541d97ca6a3592dd75beb9c9646e40c511b82496cfc3926956"); - - assert_eq!(expected, x_mod.retrieve()); - } -} diff --git a/src/modular/residue/mul.rs b/src/modular/residue/mul.rs deleted file mode 100644 index 805e09060..000000000 --- a/src/modular/residue/mul.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! Multiplications between residues with a constant modulus. - -use core::{ - marker::PhantomData, - ops::{Mul, MulAssign}, -}; - -use crate::{ - modular::mul::{mul_montgomery_form, square_montgomery_form}, - traits::Square, -}; - -use super::{Residue, ResidueParams}; - -impl, const LIMBS: usize> Residue { - /// Multiplies by `rhs`. - pub const fn mul(&self, rhs: &Self) -> Self { - Self { - montgomery_form: mul_montgomery_form( - &self.montgomery_form, - &rhs.montgomery_form, - &MOD::MODULUS.0, - MOD::MOD_NEG_INV, - ), - phantom: PhantomData, - } - } - - /// Computes the (reduced) square of a residue. - pub const fn square(&self) -> Self { - Self { - montgomery_form: square_montgomery_form( - &self.montgomery_form, - &MOD::MODULUS.0, - MOD::MOD_NEG_INV, - ), - phantom: PhantomData, - } - } -} - -impl, const LIMBS: usize> Mul<&Residue> - for &Residue -{ - type Output = Residue; - fn mul(self, rhs: &Residue) -> Residue { - self.mul(rhs) - } -} - -impl, const LIMBS: usize> Mul> - for &Residue -{ - type Output = Residue; - #[allow(clippy::op_ref)] - fn mul(self, rhs: Residue) -> Residue { - self * &rhs - } -} - -impl, const LIMBS: usize> Mul<&Residue> - for Residue -{ - type Output = Residue; - #[allow(clippy::op_ref)] - fn mul(self, rhs: &Residue) -> Residue { - &self * rhs - } -} - -impl, const LIMBS: usize> Mul> - for Residue -{ - type Output = Residue; - fn mul(self, rhs: Residue) -> Residue { - &self * &rhs - } -} - -impl, const LIMBS: usize> MulAssign<&Self> for Residue { - fn mul_assign(&mut self, rhs: &Residue) { - *self = *self * rhs; - } -} - -impl, const LIMBS: usize> MulAssign for Residue { - fn mul_assign(&mut self, rhs: Self) { - *self *= &rhs; - } -} - -impl, const LIMBS: usize> Square for Residue { - fn square(&self) -> Self { - Residue::square(self) - } -} diff --git a/src/modular/residue/neg.rs b/src/modular/residue/neg.rs deleted file mode 100644 index 483a35e98..000000000 --- a/src/modular/residue/neg.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Negations of residues with a constant modulus. - -use super::{Residue, ResidueParams}; -use core::ops::Neg; - -impl, const LIMBS: usize> Residue { - /// Negates the number. - pub const fn neg(&self) -> Self { - Self::ZERO.sub(self) - } -} - -impl, const LIMBS: usize> Neg for Residue { - type Output = Self; - fn neg(self) -> Self { - Residue::neg(&self) - } -} - -impl, const LIMBS: usize> Neg for &Residue { - type Output = Residue; - fn neg(self) -> Residue { - Residue::neg(self) - } -} - -#[cfg(test)] -mod tests { - use crate::{const_residue, impl_modulus, modular::residue::ResidueParams, U256}; - - impl_modulus!( - Modulus, - U256, - "15477BCCEFE197328255BFA79A1217899016D927EF460F4FF404029D24FA4409" - ); - - #[test] - fn test_negate() { - let x = - U256::from_be_hex("77117F1273373C26C700D076B3F780074D03339F56DD0EFB60E7F58441FD3685"); - let x_mod = const_residue!(x, Modulus); - - let res = -x_mod; - let expected = - U256::from_be_hex("089B67BB2C124F084701AD76E8750D321385E35044C74CE457301A2A9BE061B1"); - - assert_eq!(res.retrieve(), expected); - } -} diff --git a/src/modular/residue/sub.rs b/src/modular/residue/sub.rs deleted file mode 100644 index afc178293..000000000 --- a/src/modular/residue/sub.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! Subtractions between residues with a constant modulus. - -use super::{Residue, ResidueParams}; -use crate::modular::sub::sub_montgomery_form; -use core::ops::{Sub, SubAssign}; - -impl, const LIMBS: usize> Residue { - /// Subtracts `rhs`. - pub const fn sub(&self, rhs: &Self) -> Self { - Self { - montgomery_form: sub_montgomery_form( - &self.montgomery_form, - &rhs.montgomery_form, - &MOD::MODULUS.0, - ), - phantom: core::marker::PhantomData, - } - } -} - -impl, const LIMBS: usize> Sub<&Residue> - for &Residue -{ - type Output = Residue; - fn sub(self, rhs: &Residue) -> Residue { - self.sub(rhs) - } -} - -impl, const LIMBS: usize> Sub> - for &Residue -{ - type Output = Residue; - #[allow(clippy::op_ref)] - fn sub(self, rhs: Residue) -> Residue { - self - &rhs - } -} - -impl, const LIMBS: usize> Sub<&Residue> - for Residue -{ - type Output = Residue; - #[allow(clippy::op_ref)] - fn sub(self, rhs: &Residue) -> Residue { - &self - rhs - } -} - -impl, const LIMBS: usize> Sub> - for Residue -{ - type Output = Residue; - fn sub(self, rhs: Residue) -> Residue { - &self - &rhs - } -} - -impl, const LIMBS: usize> SubAssign<&Self> for Residue { - fn sub_assign(&mut self, rhs: &Self) { - *self = *self - rhs; - } -} - -impl, const LIMBS: usize> SubAssign for Residue { - fn sub_assign(&mut self, rhs: Self) { - *self -= &rhs; - } -} - -#[cfg(test)] -mod tests { - use crate::{const_residue, impl_modulus, modular::residue::ResidueParams, U256}; - - impl_modulus!( - Modulus, - U256, - "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" - ); - - #[test] - fn sub_overflow() { - let x = - U256::from_be_hex("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"); - let mut x_mod = const_residue!(x, Modulus); - - let y = - U256::from_be_hex("d5777c45019673125ad240f83094d4252d829516fac8601ed01979ec1ec1a251"); - let y_mod = const_residue!(y, Modulus); - - x_mod -= &y_mod; - - let expected = - U256::from_be_hex("6f357a71e1d5a03167f34879d469352add829491c6df41ddff65387d7ed56f56"); - - assert_eq!(expected, x_mod.retrieve()); - } -} diff --git a/src/uint/boxed/mul_mod.rs b/src/uint/boxed/mul_mod.rs index adfa9af23..40cd112b5 100644 --- a/src/uint/boxed/mul_mod.rs +++ b/src/uint/boxed/mul_mod.rs @@ -1,7 +1,7 @@ //! [`BoxedUint`] modular multiplication operations. use crate::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, primitives::mul_rem, BoxedUint, Limb, MulMod, WideWord, Word, }; @@ -18,10 +18,10 @@ impl BoxedUint { // Barrett reduction instead. // // It's worth potentially exploring other approaches to improve efficiency. - match Option::::from(BoxedResidueParams::new(p.clone())) { + match Option::::from(BoxedMontyParams::new(p.clone())) { Some(params) => { - let lhs = BoxedResidue::new(self.clone(), params.clone()); - let rhs = BoxedResidue::new(rhs.clone(), params); + let lhs = BoxedMontyForm::new(self.clone(), params.clone()); + let rhs = BoxedMontyForm::new(rhs.clone(), params); let ret = lhs * rhs; ret.retrieve() } diff --git a/src/uint/mul_mod.rs b/src/uint/mul_mod.rs index a77213a26..6baa96aef 100644 --- a/src/uint/mul_mod.rs +++ b/src/uint/mul_mod.rs @@ -1,7 +1,7 @@ //! [`Uint`] modular multiplication operations. use crate::{ - modular::{DynResidue, DynResidueParams}, + modular::{MontyForm, MontyParams}, primitives::mul_rem, Limb, MulMod, Uint, WideWord, Word, }; @@ -18,10 +18,10 @@ impl Uint { // Barrett reduction instead. // // It's worth potentially exploring other approaches to improve efficiency. - match DynResidueParams::new(p).into() { + match MontyParams::new(p).into() { Some(params) => { - let lhs = DynResidue::new(self, params); - let rhs = DynResidue::new(rhs, params); + let lhs = MontyForm::new(self, params); + let rhs = MontyForm::new(rhs, params); let ret = lhs * rhs; ret.retrieve() } diff --git a/tests/boxed_monty_form.proptest-regressions b/tests/boxed_monty_form.proptest-regressions new file mode 100644 index 000000000..aa167fe41 --- /dev/null +++ b/tests/boxed_monty_form.proptest-regressions @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc a2dbf0ee6304db81982e37ad9d9145a0f9de45730b9c41221dbf9fdfb9a246c5 # shrinks to a = BoxedUint(0x0000000000000002), b = BoxedUint(0x0000000000000100), n = BoxedMontyParams { modulus: BoxedUint(0x0000000000000003), one: BoxedUint(0x0000000000000001), r2: BoxedUint(0x0000000000000001), r3: BoxedUint(0x0000000000000001), mod_neg_inv: Limb(0x5555555555555555) } +cc 00f163e6056fad81f0a00e33ff628c3948b7e2f5f2f806d201de874468ec8c57 # shrinks to (a, b) = (BoxedMontyForm { montgomery_form: BoxedUint(0x5A7D315F0CCBDB393E483EE367A05463992BFA5D0EFACB3D2B0FFC152B75B940), params: BoxedMontyParams { modulus: BoxedUint(0xBF645819DA525D921D2D072521783F02155C5BD7158CE3EB49BE89BE58CF3957), one: BoxedUint(0x409BA7E625ADA26DE2D2F8DADE87C0FDEAA3A428EA731C14B6417641A730C6A9), r2: BoxedUint(0x17629F64058CC036FAFFAF9D2EB492A2D85A7DC55FD575A92058DB0582647317), r3: BoxedUint(0x3BF020F12134E941004697534F9D9AA4DD43E7B38509F06A7D3EF62AC227F2B6), mod_neg_inv: Limb(0xD7237775D94B3D99) } }, BoxedMontyForm { montgomery_form: BoxedUint(0x7FFC7CA9B2EFA758EB87DCB0512F5D060503033E8D7D8F8E4478F0B046C9AC94), params: BoxedMontyParams { modulus: BoxedUint(0xBF645819DA525D921D2D072521783F02155C5BD7158CE3EB49BE89BE58CF3957), one: BoxedUint(0x409BA7E625ADA26DE2D2F8DADE87C0FDEAA3A428EA731C14B6417641A730C6A9), r2: BoxedUint(0x17629F64058CC036FAFFAF9D2EB492A2D85A7DC55FD575A92058DB0582647317), r3: BoxedUint(0x3BF020F12134E941004697534F9D9AA4DD43E7B38509F06A7D3EF62AC227F2B6), mod_neg_inv: Limb(0xD7237775D94B3D99) } }) +cc 234544db24f3fa99fbd88776d9d9b03194478068e70719788deb9087d7d955c9 # shrinks to a = BoxedUint(0xAAF6458F8A12304356B649B991D597FC6C455A4B3D3916D7EFDD3087D7127E62666A2FEB411E4F11), b = BoxedUint(0xD092E81F038C1F6E475513DED53DC7CE77ADF51BF3DCC0A7A2C00D0701EDFF368924BF9AC5C52882), n = BoxedMontyParams { modulus: BoxedUint(0x77980BCC1B3AC570148BD14A1EFCCE2A7F866BA64AEE9B92D4FB9C54CB0D990BA9A68664194AA4E9A39CC068AB2EBE87), one: BoxedUint(0x10CFE867C98A751FD6E85D6BC20663AB00F328B36A22C8DA5608C75669E4CDE8ACB2F337CD6AB62CB8C67F2EA9A282F2), r2: BoxedUint(0x6F241F6AFDA802307573B0865EA774EF46CA757D710607B0CC9920AEB106B125A3C5E2742A89CF254D44ABFC66319B45), r3: BoxedUint(0x62D52BBD9502DEEC47467ABDA7C6CF2AA05D58866B78CA2EA948224155046964E3B43F8F8CD01A9A362B66EE34A4D759), mod_neg_inv: Limb(0x9AABE2A2584258C9) } diff --git a/tests/boxed_residue_proptests.rs b/tests/boxed_monty_form.rs similarity index 76% rename from tests/boxed_residue_proptests.rs rename to tests/boxed_monty_form.rs index 4b4b82790..490f7ba51 100644 --- a/tests/boxed_residue_proptests.rs +++ b/tests/boxed_monty_form.rs @@ -1,9 +1,9 @@ -//! Equivalence tests between `crypto_bigint::BoxedResidue` and `num-bigint`. +//! Equivalence tests between `crypto_bigint::BoxedMontyForm` and `num-bigint`. #![cfg(feature = "alloc")] use crypto_bigint::{ - modular::{BoxedResidue, BoxedResidueParams}, + modular::{BoxedMontyForm, BoxedMontyParams}, BoxedUint, Integer, Limb, NonZero, }; use num_bigint::{BigUint, ModInverse}; @@ -14,11 +14,11 @@ fn to_biguint(uint: &BoxedUint) -> BigUint { BigUint::from_bytes_be(&uint.to_be_bytes()) } -fn retrieve_biguint(residue: &BoxedResidue) -> BigUint { - to_biguint(&residue.retrieve()) +fn retrieve_biguint(monty_form: &BoxedMontyForm) -> BigUint { + to_biguint(&monty_form.retrieve()) } -fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { +fn reduce(n: &BoxedUint, p: BoxedMontyParams) -> BoxedMontyForm { let bits_precision = p.modulus().bits_precision(); let modulus = NonZero::new(p.modulus().clone()).unwrap(); @@ -29,7 +29,7 @@ fn reduce(n: &BoxedUint, p: BoxedResidueParams) -> BoxedResidue { }; let n_reduced = n.rem_vartime(&modulus).widen(p.bits_precision()); - BoxedResidue::new(n_reduced, p) + BoxedMontyForm::new(n_reduced, p) } prop_compose! { @@ -43,23 +43,23 @@ prop_compose! { } prop_compose! { /// Generate a random odd modulus. - fn modulus()(mut n in uint()) -> BoxedResidueParams { + fn modulus()(mut n in uint()) -> BoxedMontyParams { if n.is_even().into() { n = n.wrapping_add(&BoxedUint::one()); } - BoxedResidueParams::new(n).expect("modulus should be valid") + BoxedMontyParams::new(n).expect("modulus should be valid") } } prop_compose! { - /// Generate a single residue. - fn residue()(a in uint(), n in modulus()) -> BoxedResidue { + /// Generate a single Montgomery form integer. + fn monty_form()(a in uint(), n in modulus()) -> BoxedMontyForm { reduce(&a, n.clone()) } } prop_compose! { - /// Generate two residues with a common modulus. - fn residue_pair()(a in uint(), b in uint(), n in modulus()) -> (BoxedResidue, BoxedResidue) { + /// Generate two Montgomery form integers with a common modulus. + fn monty_form_pair()(a in uint(), b in uint(), n in modulus()) -> (BoxedMontyForm, BoxedMontyForm) { (reduce(&a, n.clone()), reduce(&b, n.clone())) } } @@ -71,15 +71,15 @@ proptest! { n = n.wrapping_add(&BoxedUint::one()); } - let params1 = BoxedResidueParams::new(n.clone()).unwrap(); - let params2 = BoxedResidueParams::new_vartime(n).unwrap(); + let params1 = BoxedMontyParams::new(n.clone()).unwrap(); + let params2 = BoxedMontyParams::new_vartime(n).unwrap(); prop_assert_eq!(params1, params2); } #[test] fn inv(x in uint(), n in modulus()) { let x = reduce(&x, n.clone()); - let actual = Option::::from(x.invert()).map(|a| a.retrieve()); + let actual = Option::::from(x.invert()).map(|a| a.retrieve()); let x_bi = retrieve_biguint(&x); let n_bi = to_biguint(n.modulus()); @@ -93,7 +93,7 @@ proptest! { } #[test] - fn mul((a, b) in residue_pair()) { + fn mul((a, b) in monty_form_pair()) { let p = a.params().modulus(); let actual = &a * &b; prop_assert!(actual.as_montgomery() < a.params().modulus()); @@ -107,7 +107,7 @@ proptest! { } #[test] - fn square(a in residue()) { + fn square(a in monty_form()) { let p = a.params().modulus(); let actual = a.square(); prop_assert!(actual.as_montgomery() < a.params().modulus()); diff --git a/tests/boxed_residue_proptests.proptest-regressions b/tests/boxed_residue_proptests.proptest-regressions deleted file mode 100644 index 236d3dec5..000000000 --- a/tests/boxed_residue_proptests.proptest-regressions +++ /dev/null @@ -1,9 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc a2dbf0ee6304db81982e37ad9d9145a0f9de45730b9c41221dbf9fdfb9a246c5 # shrinks to a = BoxedUint(0x0000000000000002), b = BoxedUint(0x0000000000000100), n = BoxedResidueParams { modulus: BoxedUint(0x0000000000000003), r: BoxedUint(0x0000000000000001), r2: BoxedUint(0x0000000000000001), r3: BoxedUint(0x0000000000000001), mod_neg_inv: Limb(0x5555555555555555) } -cc 00f163e6056fad81f0a00e33ff628c3948b7e2f5f2f806d201de874468ec8c57 # shrinks to (a, b) = (BoxedResidue { montgomery_form: BoxedUint(0x5A7D315F0CCBDB393E483EE367A05463992BFA5D0EFACB3D2B0FFC152B75B940), residue_params: BoxedResidueParams { modulus: BoxedUint(0xBF645819DA525D921D2D072521783F02155C5BD7158CE3EB49BE89BE58CF3957), r: BoxedUint(0x409BA7E625ADA26DE2D2F8DADE87C0FDEAA3A428EA731C14B6417641A730C6A9), r2: BoxedUint(0x17629F64058CC036FAFFAF9D2EB492A2D85A7DC55FD575A92058DB0582647317), r3: BoxedUint(0x3BF020F12134E941004697534F9D9AA4DD43E7B38509F06A7D3EF62AC227F2B6), mod_neg_inv: Limb(0xD7237775D94B3D99) } }, BoxedResidue { montgomery_form: BoxedUint(0x7FFC7CA9B2EFA758EB87DCB0512F5D060503033E8D7D8F8E4478F0B046C9AC94), residue_params: BoxedResidueParams { modulus: BoxedUint(0xBF645819DA525D921D2D072521783F02155C5BD7158CE3EB49BE89BE58CF3957), r: BoxedUint(0x409BA7E625ADA26DE2D2F8DADE87C0FDEAA3A428EA731C14B6417641A730C6A9), r2: BoxedUint(0x17629F64058CC036FAFFAF9D2EB492A2D85A7DC55FD575A92058DB0582647317), r3: BoxedUint(0x3BF020F12134E941004697534F9D9AA4DD43E7B38509F06A7D3EF62AC227F2B6), mod_neg_inv: Limb(0xD7237775D94B3D99) } }) -cc 234544db24f3fa99fbd88776d9d9b03194478068e70719788deb9087d7d955c9 # shrinks to a = BoxedUint(0xAAF6458F8A12304356B649B991D597FC6C455A4B3D3916D7EFDD3087D7127E62666A2FEB411E4F11), b = BoxedUint(0xD092E81F038C1F6E475513DED53DC7CE77ADF51BF3DCC0A7A2C00D0701EDFF368924BF9AC5C52882), n = BoxedResidueParams { modulus: BoxedUint(0x77980BCC1B3AC570148BD14A1EFCCE2A7F866BA64AEE9B92D4FB9C54CB0D990BA9A68664194AA4E9A39CC068AB2EBE87), r: BoxedUint(0x10CFE867C98A751FD6E85D6BC20663AB00F328B36A22C8DA5608C75669E4CDE8ACB2F337CD6AB62CB8C67F2EA9A282F2), r2: BoxedUint(0x6F241F6AFDA802307573B0865EA774EF46CA757D710607B0CC9920AEB106B125A3C5E2742A89CF254D44ABFC66319B45), r3: BoxedUint(0x62D52BBD9502DEEC47467ABDA7C6CF2AA05D58866B78CA2EA948224155046964E3B43F8F8CD01A9A362B66EE34A4D759), mod_neg_inv: Limb(0x9AABE2A2584258C9) } diff --git a/tests/residue.rs b/tests/const_monty_form.rs similarity index 72% rename from tests/residue.rs rename to tests/const_monty_form.rs index 269a4a9ac..8af636b4f 100644 --- a/tests/residue.rs +++ b/tests/const_monty_form.rs @@ -1,6 +1,6 @@ -//! Equivalence tests between `crypto_bigint::Residue` and `num-bigint`. +//! Equivalence tests between `crypto_bigint::ConstMontyForm` and `num-bigint`. -use crypto_bigint::{impl_modulus, modular::ResidueParams, Encoding, Invert, Inverter, U256}; +use crypto_bigint::{impl_modulus, modular::ConstMontyParams, Encoding, Invert, Inverter, U256}; use num_bigint::{BigUint, ModInverse}; use proptest::prelude::*; @@ -10,18 +10,18 @@ impl_modulus!( "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" ); -type Residue = crypto_bigint::modular::Residue; +type ConstMontyForm = crypto_bigint::modular::ConstMontyForm; fn to_biguint(uint: &U256) -> BigUint { BigUint::from_bytes_le(uint.to_le_bytes().as_ref()) } -fn retrieve_biguint(residue: &Residue) -> BigUint { - to_biguint(&residue.retrieve()) +fn retrieve_biguint(monty_form: &ConstMontyForm) -> BigUint { + to_biguint(&monty_form.retrieve()) } -fn reduce(n: &U256) -> Residue { - Residue::new(&n) +fn reduce(n: &U256) -> ConstMontyForm { + ConstMontyForm::new(&n) } prop_compose! { @@ -29,18 +29,12 @@ prop_compose! { U256::from_le_slice(&bytes) } } -prop_compose! { - /// Generate a single residue. - fn residue()(a in uint()) -> Residue { - reduce(&a) - } -} proptest! { #[test] fn inv(x in uint()) { let x = reduce(&x); - let actual = Option::::from(x.invert()); + let actual = Option::::from(x.invert()); let x_bi = retrieve_biguint(&x); let n_bi = to_biguint(&Modulus::MODULUS); @@ -61,7 +55,7 @@ proptest! { fn precomputed_inv(x in uint()) { let x = reduce(&x); let inverter = Modulus::precompute_inverter(); - let actual = Option::::from(inverter.invert(&x)); + let actual = Option::::from(inverter.invert(&x)); let x_bi = retrieve_biguint(&x); let n_bi = to_biguint(&Modulus::MODULUS); diff --git a/tests/const_residue.rs b/tests/const_residue.rs deleted file mode 100644 index 5681bed18..000000000 --- a/tests/const_residue.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Test to ensure that `const_residue!` works from outside this crate. - -use crypto_bigint::{const_residue, impl_modulus, modular::ResidueParams, U64}; - -impl_modulus!(TestMod, U64, "30e4b8f030ab42f3"); - -fn _test_fun() { - let base = U64::from(2u64); - let _base_mod = const_residue!(base, TestMod); -} diff --git a/tests/dyn_residue_proptests.rs b/tests/monty_form.rs similarity index 70% rename from tests/dyn_residue_proptests.rs rename to tests/monty_form.rs index 6ab6bf617..3b3da73c6 100644 --- a/tests/dyn_residue_proptests.rs +++ b/tests/monty_form.rs @@ -1,24 +1,24 @@ -//! Equivalence tests between `crypto_bigint::DynResidue` and `num-bigint`. +//! Equivalence tests between `crypto_bigint::MontyForm` and `num-bigint`. use crypto_bigint::{Encoding, Integer, Invert, Inverter, NonZero, PrecomputeInverter, U256}; use num_bigint::{BigUint, ModInverse}; use proptest::prelude::*; -type DynResidue = crypto_bigint::modular::DynResidue<{ U256::LIMBS }>; -type DynResidueParams = crypto_bigint::modular::DynResidueParams<{ U256::LIMBS }>; +type MontyForm = crypto_bigint::modular::MontyForm<{ U256::LIMBS }>; +type MontyParams = crypto_bigint::modular::MontyParams<{ U256::LIMBS }>; fn to_biguint(uint: &U256) -> BigUint { BigUint::from_bytes_le(uint.to_le_bytes().as_ref()) } -fn retrieve_biguint(residue: &DynResidue) -> BigUint { - to_biguint(&residue.retrieve()) +fn retrieve_biguint(monty_form: &MontyForm) -> BigUint { + to_biguint(&monty_form.retrieve()) } -fn reduce(n: &U256, p: DynResidueParams) -> DynResidue { +fn reduce(n: &U256, p: MontyParams) -> MontyForm { let modulus = NonZero::new(p.modulus().clone()).unwrap(); let n_reduced = n.rem_vartime(&modulus); - DynResidue::new(&n_reduced, p) + MontyForm::new(&n_reduced, p) } prop_compose! { @@ -28,18 +28,12 @@ prop_compose! { } prop_compose! { /// Generate a random odd modulus. - fn modulus()(mut n in uint()) -> DynResidueParams { + fn modulus()(mut n in uint()) -> MontyParams { if n.is_even().into() { n = n.wrapping_add(&U256::one()); } - DynResidueParams::new(&n).expect("modulus should be valid") - } -} -prop_compose! { - /// Generate a single residue. - fn residue()(a in uint(), n in modulus()) -> DynResidue { - reduce(&a, n.clone()) + MontyParams::new(&n).expect("modulus should be valid") } } @@ -47,7 +41,7 @@ proptest! { #[test] fn inv(x in uint(), n in modulus()) { let x = reduce(&x, n.clone()); - let actual = Option::::from(x.invert()); + let actual = Option::::from(x.invert()); let x_bi = retrieve_biguint(&x); let n_bi = to_biguint(n.modulus()); @@ -68,7 +62,7 @@ proptest! { fn precomputed_inv(x in uint(), n in modulus()) { let x = reduce(&x, n.clone()); let inverter = x.params().precompute_inverter(); - let actual = Option::::from(inverter.invert(&x)); + let actual = Option::::from(inverter.invert(&x)); let x_bi = retrieve_biguint(&x); let n_bi = to_biguint(n.modulus()); diff --git a/tests/uint_proptests.rs b/tests/uint_proptests.rs index 6f6e36763..0cb97b30f 100644 --- a/tests/uint_proptests.rs +++ b/tests/uint_proptests.rs @@ -1,7 +1,7 @@ //! Equivalence tests between `crypto_bigint::Uint` and `num_bigint::BigUint`. use crypto_bigint::{ - modular::{DynResidue, DynResidueParams}, + modular::{MontyForm, MontyParams}, Encoding, Integer, Limb, NonZero, Word, U256, }; use num_bigint::BigUint; @@ -397,22 +397,22 @@ proptest! { } #[test] - fn residue_pow(a in uint_mod_p(P), b in uint()) { + fn monty_form_pow(a in uint_mod_p(P), b in uint()) { let a_bi = to_biguint(&a); let b_bi = to_biguint(&b); let p_bi = to_biguint(&P); let expected = to_uint(a_bi.modpow(&b_bi, &p_bi)); - let params = DynResidueParams::new(&P).unwrap(); - let a_m = DynResidue::new(&a, params); + let params = MontyParams::new(&P).unwrap(); + let a_m = MontyForm::new(&a, params); let actual = a_m.pow(&b).retrieve(); assert_eq!(expected, actual); } #[test] - fn residue_pow_bounded_exp(a in uint_mod_p(P), b in uint(), exponent_bits in any::()) { + fn monty_form_pow_bounded_exp(a in uint_mod_p(P), b in uint(), exponent_bits in any::()) { let b_masked = b & (U256::ONE << exponent_bits as u32).wrapping_sub(&U256::ONE); let a_bi = to_biguint(&a); @@ -421,15 +421,15 @@ proptest! { let expected = to_uint(a_bi.modpow(&b_bi, &p_bi)); - let params = DynResidueParams::new(&P).unwrap(); - let a_m = DynResidue::new(&a, params); + let params = MontyParams::new(&P).unwrap(); + let a_m = MontyForm::new(&a, params); let actual = a_m.pow_bounded_exp(&b, exponent_bits.into()).retrieve(); assert_eq!(expected, actual); } #[test] - fn residue_div_by_2(a in uint_mod_p(P)) { + fn monty_form_div_by_2(a in uint_mod_p(P)) { let a_bi = to_biguint(&a); let p_bi = to_biguint(&P); let two = BigUint::from(2u32); @@ -442,8 +442,8 @@ proptest! { }; let expected = to_uint(expected); - let params = DynResidueParams::new(&P).unwrap(); - let a_m = DynResidue::new(&a, params); + let params = MontyParams::new(&P).unwrap(); + let a_m = MontyForm::new(&a, params); let actual = a_m.div_by_2().retrieve(); assert_eq!(expected, actual);