Skip to content

Commit 8416c24

Browse files
authored
Add traits to connect integers and residue represenations (#431)
- add `Monty` associated type to `Integer` linking it to the corresponding Montgomery form - add `Monty` trait with an associated type linking back to the corresponding `Integer` and a bunch of bounds (similar to `Integer`) - remove the bound on `Square` which made it hard to make `Square` a bound to other traits. This means that there's no default implementation anymore. - add `SquareAssign` trait.
1 parent 1ef8172 commit 8416c24

File tree

7 files changed

+130
-18
lines changed

7 files changed

+130
-18
lines changed

src/modular/boxed_monty_form.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::{
1212
reduction::{montgomery_reduction_boxed, montgomery_reduction_boxed_mut},
1313
Retrieve,
1414
};
15-
use crate::{BoxedUint, ConstantTimeSelect, Integer, Limb, NonZero, Word};
15+
use crate::{BoxedUint, ConstantTimeSelect, Integer, Limb, Monty, NonZero, Word};
1616
use subtle::CtOption;
1717

1818
#[cfg(feature = "std")]
@@ -251,6 +251,27 @@ impl Retrieve for BoxedMontyForm {
251251
}
252252
}
253253

254+
impl Monty for BoxedMontyForm {
255+
type Integer = BoxedUint;
256+
type Params = BoxedMontyParams;
257+
258+
fn new_params(modulus: Self::Integer) -> CtOption<Self::Params> {
259+
BoxedMontyParams::new(modulus)
260+
}
261+
262+
fn new(value: Self::Integer, params: Self::Params) -> Self {
263+
BoxedMontyForm::new(value, params)
264+
}
265+
266+
fn zero(params: Self::Params) -> Self {
267+
BoxedMontyForm::zero(params)
268+
}
269+
270+
fn one(params: Self::Params) -> Self {
271+
BoxedMontyForm::one(params)
272+
}
273+
}
274+
254275
/// Convert the given integer into the Montgomery domain.
255276
#[inline]
256277
fn convert_to_montgomery(integer: &mut BoxedUint, params: &BoxedMontyParams) {

src/modular/boxed_monty_form/mul.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
88
use super::{BoxedMontyForm, BoxedMontyParams};
99
use crate::{
10-
modular::reduction::montgomery_reduction_boxed_mut, traits::Square, uint::mul::mul_limbs,
11-
BoxedUint, Limb, Word, Zero,
10+
modular::reduction::montgomery_reduction_boxed_mut, uint::mul::mul_limbs, BoxedUint, Limb,
11+
Square, SquareAssign, Word, Zero,
1212
};
1313
use core::{
1414
borrow::Borrow,
@@ -94,6 +94,12 @@ impl Square for BoxedMontyForm {
9494
}
9595
}
9696

97+
impl SquareAssign for BoxedMontyForm {
98+
fn square_assign(&mut self) {
99+
MontgomeryMultiplier::from(self.params.borrow()).square_assign(&mut self.montgomery_form);
100+
}
101+
}
102+
97103
impl<'a> From<&'a BoxedMontyParams> for MontgomeryMultiplier<'a> {
98104
fn from(params: &'a BoxedMontyParams) -> MontgomeryMultiplier<'a> {
99105
MontgomeryMultiplier::new(&params.modulus, params.mod_neg_inv)

src/modular/monty_form.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use super::{
1313
reduction::montgomery_reduction,
1414
Retrieve,
1515
};
16-
use crate::{Limb, NonZero, Uint, Word, Zero};
16+
use crate::{Limb, Monty, NonZero, Uint, Word, Zero};
1717
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
1818

1919
/// Parameters to efficiently go to/from the Montgomery form for an odd modulus provided at runtime.
@@ -208,6 +208,27 @@ impl<const LIMBS: usize> Retrieve for MontyForm<LIMBS> {
208208
}
209209
}
210210

211+
impl<const LIMBS: usize> Monty for MontyForm<LIMBS> {
212+
type Integer = Uint<LIMBS>;
213+
type Params = MontyParams<LIMBS>;
214+
215+
fn new_params(modulus: Self::Integer) -> CtOption<Self::Params> {
216+
MontyParams::new(&modulus)
217+
}
218+
219+
fn new(value: Self::Integer, params: Self::Params) -> Self {
220+
MontyForm::new(&value, params)
221+
}
222+
223+
fn zero(params: Self::Params) -> Self {
224+
MontyForm::zero(params)
225+
}
226+
227+
fn one(params: Self::Params) -> Self {
228+
MontyForm::one(params)
229+
}
230+
}
231+
211232
impl<const LIMBS: usize, P: ConstMontyParams<LIMBS>> From<&ConstMontyForm<P, LIMBS>>
212233
for MontyForm<LIMBS>
213234
{

src/modular/monty_form/mul.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use super::MontyForm;
44
use crate::{
55
modular::mul::{mul_montgomery_form, square_montgomery_form},
6-
traits::Square,
6+
Square, SquareAssign,
77
};
88
use core::ops::{Mul, MulAssign};
99

@@ -82,3 +82,9 @@ impl<const LIMBS: usize> Square for MontyForm<LIMBS> {
8282
MontyForm::square(self)
8383
}
8484
}
85+
86+
impl<const LIMBS: usize> SquareAssign for MontyForm<LIMBS> {
87+
fn square_assign(&mut self) {
88+
*self = self.square()
89+
}
90+
}

src/traits.rs

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ pub(crate) use sealed::PrecomputeInverterWithAdjuster;
1111
use crate::{Limb, NonZero};
1212
use core::fmt::Debug;
1313
use core::ops::{
14-
Add, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, Not,
15-
Rem, Shl, ShlAssign, Shr, ShrAssign, Sub,
14+
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
15+
Mul, MulAssign, Neg, Not, Rem, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
1616
};
1717
use subtle::{
1818
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
@@ -141,6 +141,10 @@ pub trait Integer:
141141
+ WrappingShr
142142
+ Zero
143143
{
144+
/// The corresponding Montgomery representation,
145+
/// optimized for the performance of modular operations at the price of a conversion overhead.
146+
type Monty: Monty<Integer = Self>;
147+
144148
/// The value `1`.
145149
fn one() -> Self;
146150

@@ -425,14 +429,16 @@ pub trait Encoding: Sized {
425429
}
426430

427431
/// Support for optimized squaring
428-
pub trait Square: Sized
429-
where
430-
for<'a> &'a Self: Mul<&'a Self, Output = Self>,
431-
{
432-
/// Computes the same as `self.mul(self)`, but may be more efficient.
433-
fn square(&self) -> Self {
434-
self * self
435-
}
432+
pub trait Square {
433+
/// Computes the same as `self * self`, but may be more efficient.
434+
fn square(&self) -> Self;
435+
}
436+
437+
/// Support for optimized squaring in-place
438+
pub trait SquareAssign {
439+
/// Computes the same as `self * self`, but may be more efficient.
440+
/// Writes the result in `self`.
441+
fn square_assign(&mut self);
436442
}
437443

438444
/// Constant-time exponentiation.
@@ -513,3 +519,50 @@ pub trait WideningMul<Rhs = Self>: Sized {
513519
/// Perform widening multiplication.
514520
fn widening_mul(&self, rhs: Rhs) -> Self::Output;
515521
}
522+
523+
/// A representation of an integer optimized for the performance of modular operations.
524+
pub trait Monty:
525+
'static
526+
+ Clone
527+
+ Debug
528+
+ Eq
529+
+ Sized
530+
+ Send
531+
+ Sync
532+
+ Add<Output = Self>
533+
+ for<'a> Add<&'a Self, Output = Self>
534+
+ AddAssign
535+
+ for<'a> AddAssign<&'a Self>
536+
+ Sub<Output = Self>
537+
+ for<'a> Sub<&'a Self, Output = Self>
538+
+ SubAssign
539+
+ for<'a> SubAssign<&'a Self>
540+
+ Mul<Output = Self>
541+
+ for<'a> Mul<&'a Self, Output = Self>
542+
+ MulAssign
543+
+ for<'a> MulAssign<&'a Self>
544+
+ Neg<Output = Self>
545+
+ PowBoundedExp<Self::Integer>
546+
+ Square
547+
+ SquareAssign
548+
{
549+
/// The original integer type.
550+
type Integer: Integer<Monty = Self>;
551+
552+
/// The precomputed data needed for this representation.
553+
type Params: Clone;
554+
555+
/// Create the precomputed data for Montgomery representation of integers modulo `modulus`.
556+
///
557+
/// `modulus` must be odd, otherwise returns `None`.
558+
fn new_params(modulus: Self::Integer) -> CtOption<Self::Params>;
559+
560+
/// Convert the value into the representation using precomputed data.
561+
fn new(value: Self::Integer, params: Self::Params) -> Self;
562+
563+
/// Returns zero in this representation.
564+
fn zero(params: Self::Params) -> Self;
565+
566+
/// Returns one in this representation.
567+
fn one(params: Self::Params) -> Self;
568+
}

src/uint.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ pub(crate) mod boxed;
4040
mod rand;
4141

4242
use crate::{
43-
modular::BernsteinYangInverter, Bounded, ConstCtOption, Constants, Encoding, FixedInteger,
44-
Integer, Limb, NonZero, PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant,
43+
modular::{BernsteinYangInverter, MontyForm},
44+
Bounded, ConstCtOption, Constants, Encoding, FixedInteger, Integer, Limb, NonZero,
45+
PrecomputeInverter, PrecomputeInverterWithAdjuster, Word, ZeroConstant,
4546
};
4647
use core::fmt;
4748
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
@@ -235,6 +236,8 @@ impl<const LIMBS: usize> FixedInteger for Uint<LIMBS> {
235236
}
236237

237238
impl<const LIMBS: usize> Integer for Uint<LIMBS> {
239+
type Monty = MontyForm<LIMBS>;
240+
238241
fn one() -> Self {
239242
Self::ONE
240243
}

src/uint/boxed.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod sub_mod;
2525
#[cfg(feature = "rand_core")]
2626
mod rand;
2727

28-
use crate::{Integer, Limb, NonZero, Word, Zero};
28+
use crate::{modular::BoxedMontyForm, Integer, Limb, NonZero, Word, Zero};
2929
use alloc::{boxed::Box, vec, vec::Vec};
3030
use core::fmt;
3131
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
@@ -284,6 +284,8 @@ impl Default for BoxedUint {
284284
}
285285

286286
impl Integer for BoxedUint {
287+
type Monty = BoxedMontyForm;
288+
287289
fn one() -> Self {
288290
Self::one()
289291
}

0 commit comments

Comments
 (0)