From 8b550fb1b32a6223b298dede0a9c360f509e8ecf Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Thu, 14 Dec 2023 16:22:49 -0800 Subject: [PATCH 1/6] Add `HasResidueRepr` and `ResidueRepr` traits to connect integers and residue representations --- src/modular/boxed_monty_form.rs | 23 ++++++++++++++++++++++- src/modular/monty_form.rs | 23 ++++++++++++++++++++++- src/traits.rs | 30 ++++++++++++++++++++++++++++++ src/uint.rs | 9 +++++++-- src/uint/boxed.rs | 6 +++++- 5 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/modular/boxed_monty_form.rs b/src/modular/boxed_monty_form.rs index c2b3f2a1..f524af90 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, MontyFormLike, NonZero, Word}; use subtle::CtOption; #[cfg(feature = "std")] @@ -251,6 +251,27 @@ impl Retrieve for BoxedMontyForm { } } +impl MontyFormLike for BoxedMontyForm { + type Raw = BoxedUint; + type Params = BoxedMontyParams; + + fn new_params(modulus: Self::Raw) -> CtOption { + BoxedMontyParams::new(modulus) + } + + fn new(value: Self::Raw, 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/monty_form.rs b/src/modular/monty_form.rs index e2c7ba58..ba84410a 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, MontyFormLike, 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 MontyFormLike for MontyForm { + type Raw = Uint; + type Params = MontyParams; + + fn new_params(modulus: Self::Raw) -> CtOption { + MontyParams::new(&modulus) + } + + fn new(value: Self::Raw, 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/traits.rs b/src/traits.rs index 8ade6321..8fee0d01 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -513,3 +513,33 @@ pub trait WideningMul: Sized { /// Perform widening multiplication. fn widening_mul(&self, rhs: Rhs) -> Self::Output; } + +/// This integer has a representation optimized for the performance of modular operations. +pub trait HasMontyForm { + /// The representation type. + type MontyForm: MontyFormLike; +} + +/// A representation of an integer optimized for the performance of modular operations. +pub trait MontyFormLike { + /// The original integer type. + type Raw: HasMontyForm; + + /// The precomputed data needed for this representation. + type Params: Clone; + + /// Create the precomputed data. + /// + /// Can return `None` if `modulus` is not valid for the representation; + /// see the documentation of the specific type for the requirements. + fn new_params(modulus: Self::Raw) -> CtOption; + + /// Convert the value into the representation using precomputed data. + fn new(value: Self::Raw, 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..8ce9d54d 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, HasMontyForm, Integer, Limb, + NonZero, PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant, }; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; @@ -260,6 +261,10 @@ impl Integer for Uint { } } +impl HasMontyForm for Uint { + type MontyForm = MontyForm; +} + impl ZeroConstant for Uint { const ZERO: Self = Self::ZERO; } diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 7939d956..2eca7d9d 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, HasMontyForm, Integer, Limb, NonZero, Word, Zero}; use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; @@ -343,6 +343,10 @@ impl num_traits::One for BoxedUint { } } +impl HasMontyForm for BoxedUint { + type MontyForm = BoxedMontyForm; +} + #[cfg(feature = "zeroize")] impl Zeroize for BoxedUint { fn zeroize(&mut self) { From 63361081b8220aede70e05b3ef5df6a34f97485f Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 20 Dec 2023 11:36:51 -0800 Subject: [PATCH 2/6] Make the Montgomery form type an associated type of Integer --- src/modular/boxed_monty_form.rs | 6 +++--- src/modular/monty_form.rs | 6 +++--- src/traits.rs | 16 +++++++--------- src/uint.rs | 10 ++++------ src/uint/boxed.rs | 8 +++----- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/modular/boxed_monty_form.rs b/src/modular/boxed_monty_form.rs index f524af90..f27ea0b4 100644 --- a/src/modular/boxed_monty_form.rs +++ b/src/modular/boxed_monty_form.rs @@ -252,14 +252,14 @@ impl Retrieve for BoxedMontyForm { } impl MontyFormLike for BoxedMontyForm { - type Raw = BoxedUint; + type Integer = BoxedUint; type Params = BoxedMontyParams; - fn new_params(modulus: Self::Raw) -> CtOption { + fn new_params(modulus: Self::Integer) -> CtOption { BoxedMontyParams::new(modulus) } - fn new(value: Self::Raw, params: Self::Params) -> Self { + fn new(value: Self::Integer, params: Self::Params) -> Self { BoxedMontyForm::new(value, params) } diff --git a/src/modular/monty_form.rs b/src/modular/monty_form.rs index ba84410a..fa2ffbf3 100644 --- a/src/modular/monty_form.rs +++ b/src/modular/monty_form.rs @@ -209,14 +209,14 @@ impl Retrieve for MontyForm { } impl MontyFormLike for MontyForm { - type Raw = Uint; + type Integer = Uint; type Params = MontyParams; - fn new_params(modulus: Self::Raw) -> CtOption { + fn new_params(modulus: Self::Integer) -> CtOption { MontyParams::new(&modulus) } - fn new(value: Self::Raw, params: Self::Params) -> Self { + fn new(value: Self::Integer, params: Self::Params) -> Self { MontyForm::new(&value, params) } diff --git a/src/traits.rs b/src/traits.rs index 8fee0d01..6ac52d26 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -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 MontyForm: MontyFormLike; + /// The value `1`. fn one() -> Self; @@ -514,16 +518,10 @@ pub trait WideningMul: Sized { fn widening_mul(&self, rhs: Rhs) -> Self::Output; } -/// This integer has a representation optimized for the performance of modular operations. -pub trait HasMontyForm { - /// The representation type. - type MontyForm: MontyFormLike; -} - /// A representation of an integer optimized for the performance of modular operations. pub trait MontyFormLike { /// The original integer type. - type Raw: HasMontyForm; + type Integer: Integer; /// The precomputed data needed for this representation. type Params: Clone; @@ -532,10 +530,10 @@ pub trait MontyFormLike { /// /// Can return `None` if `modulus` is not valid for the representation; /// see the documentation of the specific type for the requirements. - fn new_params(modulus: Self::Raw) -> CtOption; + fn new_params(modulus: Self::Integer) -> CtOption; /// Convert the value into the representation using precomputed data. - fn new(value: Self::Raw, params: Self::Params) -> Self; + fn new(value: Self::Integer, params: Self::Params) -> Self; /// Returns zero in this representation. fn zero(params: Self::Params) -> Self; diff --git a/src/uint.rs b/src/uint.rs index 8ce9d54d..5dfea85f 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -41,8 +41,8 @@ mod rand; use crate::{ modular::{BernsteinYangInverter, MontyForm}, - Bounded, ConstCtOption, Constants, Encoding, FixedInteger, HasMontyForm, Integer, Limb, - NonZero, PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant, + Bounded, ConstCtOption, Constants, Encoding, FixedInteger, Integer, Limb, NonZero, + PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant, }; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; @@ -236,6 +236,8 @@ impl FixedInteger for Uint { } impl Integer for Uint { + type MontyForm = MontyForm; + fn one() -> Self { Self::ONE } @@ -261,10 +263,6 @@ impl Integer for Uint { } } -impl HasMontyForm for Uint { - type MontyForm = MontyForm; -} - impl ZeroConstant for Uint { const ZERO: Self = Self::ZERO; } diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 2eca7d9d..673517f4 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::{modular::BoxedMontyForm, HasMontyForm, 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 MontyForm = BoxedMontyForm; + fn one() -> Self { Self::one() } @@ -343,10 +345,6 @@ impl num_traits::One for BoxedUint { } } -impl HasMontyForm for BoxedUint { - type MontyForm = BoxedMontyForm; -} - #[cfg(feature = "zeroize")] impl Zeroize for BoxedUint { fn zeroize(&mut self) { From 35c46c722894cbe63e931290e7f3afcb69d3b088 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 20 Dec 2023 12:59:08 -0800 Subject: [PATCH 3/6] Add a bunch of trait bounds to MontyFormLike --- src/modular/boxed_monty_form/mul.rs | 10 ++++-- src/modular/monty_form/mul.rs | 8 ++++- src/traits.rs | 48 ++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 14 deletions(-) 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/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 6ac52d26..6155cca7 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, @@ -429,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. @@ -519,7 +521,31 @@ pub trait WideningMul: Sized { } /// A representation of an integer optimized for the performance of modular operations. -pub trait MontyFormLike { +pub trait MontyFormLike: + '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; From 9f68db3c1cd6c032ff866764c59a6ee453ebdc98 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 20 Dec 2023 13:02:49 -0800 Subject: [PATCH 4/6] Rename the trait to Monty --- src/modular/boxed_monty_form.rs | 4 ++-- src/modular/monty_form.rs | 4 ++-- src/traits.rs | 6 +++--- src/uint.rs | 2 +- src/uint/boxed.rs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/modular/boxed_monty_form.rs b/src/modular/boxed_monty_form.rs index f27ea0b4..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, MontyFormLike, NonZero, Word}; +use crate::{BoxedUint, ConstantTimeSelect, Integer, Limb, Monty, NonZero, Word}; use subtle::CtOption; #[cfg(feature = "std")] @@ -251,7 +251,7 @@ impl Retrieve for BoxedMontyForm { } } -impl MontyFormLike for BoxedMontyForm { +impl Monty for BoxedMontyForm { type Integer = BoxedUint; type Params = BoxedMontyParams; diff --git a/src/modular/monty_form.rs b/src/modular/monty_form.rs index fa2ffbf3..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, MontyFormLike, 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,7 +208,7 @@ impl Retrieve for MontyForm { } } -impl MontyFormLike for MontyForm { +impl Monty for MontyForm { type Integer = Uint; type Params = MontyParams; diff --git a/src/traits.rs b/src/traits.rs index 6155cca7..f3ab5f0d 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -143,7 +143,7 @@ pub trait Integer: { /// The corresponding Montgomery representation, /// optimized for the performance of modular operations at the price of a conversion overhead. - type MontyForm: MontyFormLike; + type Monty: Monty; /// The value `1`. fn one() -> Self; @@ -521,7 +521,7 @@ pub trait WideningMul: Sized { } /// A representation of an integer optimized for the performance of modular operations. -pub trait MontyFormLike: +pub trait Monty: 'static + Clone + Debug @@ -547,7 +547,7 @@ pub trait MontyFormLike: + SquareAssign { /// The original integer type. - type Integer: Integer; + type Integer: Integer; /// The precomputed data needed for this representation. type Params: Clone; diff --git a/src/uint.rs b/src/uint.rs index 5dfea85f..87a021b1 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -236,7 +236,7 @@ impl FixedInteger for Uint { } impl Integer for Uint { - type MontyForm = MontyForm; + type Monty = MontyForm; fn one() -> Self { Self::ONE diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 673517f4..7de00608 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -284,7 +284,7 @@ impl Default for BoxedUint { } impl Integer for BoxedUint { - type MontyForm = BoxedMontyForm; + type Monty = BoxedMontyForm; fn one() -> Self { Self::one() From 7753fd19f0e4c28e1eb613eefce32eca043b178c Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 20 Dec 2023 13:23:38 -0800 Subject: [PATCH 5/6] Fix a docstring --- src/traits.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/traits.rs b/src/traits.rs index f3ab5f0d..7fd47226 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -554,8 +554,7 @@ pub trait Monty: /// Create the precomputed data. /// - /// Can return `None` if `modulus` is not valid for the representation; - /// see the documentation of the specific type for the requirements. + /// `modulus` must be odd, otherwise returns `None`. fn new_params(modulus: Self::Integer) -> CtOption; /// Convert the value into the representation using precomputed data. From 0270d8ece0db80ab7b36b8d07ee775b45a915334 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 20 Dec 2023 13:25:02 -0800 Subject: [PATCH 6/6] Expand a docstring --- src/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traits.rs b/src/traits.rs index 7fd47226..6764ada0 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -552,7 +552,7 @@ pub trait Monty: /// The precomputed data needed for this representation. type Params: Clone; - /// Create the precomputed data. + /// 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;