diff --git a/src/modular/boxed_monty_form.rs b/src/modular/boxed_monty_form.rs index c2b3f2a1..fd956bb6 100644 --- a/src/modular/boxed_monty_form.rs +++ b/src/modular/boxed_monty_form.rs @@ -12,7 +12,7 @@ use super::{ reduction::{montgomery_reduction_boxed, montgomery_reduction_boxed_mut}, Retrieve, }; -use crate::{BoxedUint, ConstantTimeSelect, Integer, Limb, NonZero, Word}; +use crate::{BoxedUint, ConstantTimeSelect, Integer, Limb, Monty, NonZero, Word}; use subtle::CtOption; #[cfg(feature = "std")] @@ -251,6 +251,27 @@ impl Retrieve for BoxedMontyForm { } } +impl Monty for BoxedMontyForm { + type Integer = BoxedUint; + type Params = BoxedMontyParams; + + fn new_params(modulus: Self::Integer) -> CtOption { + BoxedMontyParams::new(modulus) + } + + fn new(value: Self::Integer, params: Self::Params) -> Self { + BoxedMontyForm::new(value, params) + } + + fn zero(params: Self::Params) -> Self { + BoxedMontyForm::zero(params) + } + + fn one(params: Self::Params) -> Self { + BoxedMontyForm::one(params) + } +} + /// Convert the given integer into the Montgomery domain. #[inline] fn convert_to_montgomery(integer: &mut BoxedUint, params: &BoxedMontyParams) { diff --git a/src/modular/boxed_monty_form/mul.rs b/src/modular/boxed_monty_form/mul.rs index 9a5efcb2..e3522fbb 100644 --- a/src/modular/boxed_monty_form/mul.rs +++ b/src/modular/boxed_monty_form/mul.rs @@ -7,8 +7,8 @@ use super::{BoxedMontyForm, BoxedMontyParams}; use crate::{ - modular::reduction::montgomery_reduction_boxed_mut, traits::Square, uint::mul::mul_limbs, - BoxedUint, Limb, Word, Zero, + modular::reduction::montgomery_reduction_boxed_mut, uint::mul::mul_limbs, BoxedUint, Limb, + Square, SquareAssign, Word, Zero, }; use core::{ borrow::Borrow, @@ -94,6 +94,12 @@ impl Square for BoxedMontyForm { } } +impl SquareAssign for BoxedMontyForm { + fn square_assign(&mut self) { + MontgomeryMultiplier::from(self.params.borrow()).square_assign(&mut self.montgomery_form); + } +} + impl<'a> From<&'a BoxedMontyParams> for MontgomeryMultiplier<'a> { fn from(params: &'a BoxedMontyParams) -> MontgomeryMultiplier<'a> { MontgomeryMultiplier::new(¶ms.modulus, params.mod_neg_inv) diff --git a/src/modular/monty_form.rs b/src/modular/monty_form.rs index e2c7ba58..9041b86d 100644 --- a/src/modular/monty_form.rs +++ b/src/modular/monty_form.rs @@ -13,7 +13,7 @@ use super::{ reduction::montgomery_reduction, Retrieve, }; -use crate::{Limb, NonZero, Uint, Word, Zero}; +use crate::{Limb, Monty, NonZero, Uint, Word, Zero}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; /// Parameters to efficiently go to/from the Montgomery form for an odd modulus provided at runtime. @@ -208,6 +208,27 @@ impl Retrieve for MontyForm { } } +impl Monty for MontyForm { + type Integer = Uint; + type Params = MontyParams; + + fn new_params(modulus: Self::Integer) -> CtOption { + MontyParams::new(&modulus) + } + + fn new(value: Self::Integer, params: Self::Params) -> Self { + MontyForm::new(&value, params) + } + + fn zero(params: Self::Params) -> Self { + MontyForm::zero(params) + } + + fn one(params: Self::Params) -> Self { + MontyForm::one(params) + } +} + impl> From<&ConstMontyForm> for MontyForm { diff --git a/src/modular/monty_form/mul.rs b/src/modular/monty_form/mul.rs index 7026c8fe..ef62ece7 100644 --- a/src/modular/monty_form/mul.rs +++ b/src/modular/monty_form/mul.rs @@ -3,7 +3,7 @@ use super::MontyForm; use crate::{ modular::mul::{mul_montgomery_form, square_montgomery_form}, - traits::Square, + Square, SquareAssign, }; use core::ops::{Mul, MulAssign}; @@ -82,3 +82,9 @@ impl Square for MontyForm { MontyForm::square(self) } } + +impl SquareAssign for MontyForm { + fn square_assign(&mut self) { + *self = self.square() + } +} diff --git a/src/traits.rs b/src/traits.rs index 8ade6321..6764ada0 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -11,8 +11,8 @@ pub(crate) use sealed::PrecomputeInverterWithAdjuster; use crate::{Limb, NonZero}; use core::fmt::Debug; use core::ops::{ - Add, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, Not, - Rem, Shl, ShlAssign, Shr, ShrAssign, Sub, + Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, + Mul, MulAssign, Neg, Not, Rem, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }; use subtle::{ Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess, @@ -141,6 +141,10 @@ pub trait Integer: + WrappingShr + Zero { + /// The corresponding Montgomery representation, + /// optimized for the performance of modular operations at the price of a conversion overhead. + type Monty: Monty; + /// The value `1`. fn one() -> Self; @@ -425,14 +429,16 @@ pub trait Encoding: Sized { } /// Support for optimized squaring -pub trait Square: Sized -where - for<'a> &'a Self: Mul<&'a Self, Output = Self>, -{ - /// Computes the same as `self.mul(self)`, but may be more efficient. - fn square(&self) -> Self { - self * self - } +pub trait Square { + /// Computes the same as `self * self`, but may be more efficient. + fn square(&self) -> Self; +} + +/// Support for optimized squaring in-place +pub trait SquareAssign { + /// Computes the same as `self * self`, but may be more efficient. + /// Writes the result in `self`. + fn square_assign(&mut self); } /// Constant-time exponentiation. @@ -513,3 +519,50 @@ pub trait WideningMul: Sized { /// Perform widening multiplication. fn widening_mul(&self, rhs: Rhs) -> Self::Output; } + +/// A representation of an integer optimized for the performance of modular operations. +pub trait Monty: + 'static + + Clone + + Debug + + Eq + + Sized + + Send + + Sync + + Add + + for<'a> Add<&'a Self, Output = Self> + + AddAssign + + for<'a> AddAssign<&'a Self> + + Sub + + for<'a> Sub<&'a Self, Output = Self> + + SubAssign + + for<'a> SubAssign<&'a Self> + + Mul + + for<'a> Mul<&'a Self, Output = Self> + + MulAssign + + for<'a> MulAssign<&'a Self> + + Neg + + PowBoundedExp + + Square + + SquareAssign +{ + /// The original integer type. + type Integer: Integer; + + /// The precomputed data needed for this representation. + type Params: Clone; + + /// Create the precomputed data for Montgomery representation of integers modulo `modulus`. + /// + /// `modulus` must be odd, otherwise returns `None`. + fn new_params(modulus: Self::Integer) -> CtOption; + + /// Convert the value into the representation using precomputed data. + fn new(value: Self::Integer, params: Self::Params) -> Self; + + /// Returns zero in this representation. + fn zero(params: Self::Params) -> Self; + + /// Returns one in this representation. + fn one(params: Self::Params) -> Self; +} diff --git a/src/uint.rs b/src/uint.rs index b721742e..87a021b1 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -40,8 +40,9 @@ pub(crate) mod boxed; mod rand; use crate::{ - modular::BernsteinYangInverter, Bounded, ConstCtOption, Constants, Encoding, FixedInteger, - Integer, Limb, NonZero, PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant, + modular::{BernsteinYangInverter, MontyForm}, + Bounded, ConstCtOption, Constants, Encoding, FixedInteger, Integer, Limb, NonZero, + PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant, }; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; @@ -235,6 +236,8 @@ impl FixedInteger for Uint { } impl Integer for Uint { + type Monty = MontyForm; + fn one() -> Self { Self::ONE } diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 7939d956..7de00608 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -25,7 +25,7 @@ mod sub_mod; #[cfg(feature = "rand_core")] mod rand; -use crate::{Integer, Limb, NonZero, Word, Zero}; +use crate::{modular::BoxedMontyForm, Integer, Limb, NonZero, Word, Zero}; use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; @@ -284,6 +284,8 @@ impl Default for BoxedUint { } impl Integer for BoxedUint { + type Monty = BoxedMontyForm; + fn one() -> Self { Self::one() }