Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions src/modular/boxed_monty_form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod sub;
use super::{ConstMontyParams, Retrieve, div_by_2};
use mul::BoxedMontyMultiplier;

use crate::{BoxedUint, Limb, Monty, Odd, Word};
use crate::{BoxedUint, Limb, Monty, Odd, Resize, Word};
use alloc::sync::Arc;
use subtle::Choice;

Expand Down Expand Up @@ -58,8 +58,8 @@ impl BoxedMontyParams {
// `R^2 mod modulus`, used to convert integers to Montgomery form.
let r2 = one
.square()
.rem(&modulus.as_nz_ref().widen(bits_precision * 2))
.shorten(bits_precision);
.rem(&modulus.as_nz_ref().resize_unchecked(bits_precision * 2))
.resize_unchecked(bits_precision);

// The modular inverse should always exist, because it was ensured odd above, which also ensures it's non-zero
let (inv_mod_limb, inv_mod_limb_exists) = modulus.inv_mod2k_vartime(Word::BITS);
Expand Down Expand Up @@ -102,10 +102,7 @@ impl BoxedMontyParams {
.wrapping_add(&BoxedUint::one());

// `R^2 mod modulus`, used to convert integers to Montgomery form.
let r2 = one
.square()
.rem_vartime(&modulus.as_nz_ref().widen(bits_precision * 2))
.shorten(bits_precision);
let r2 = one.square().rem_vartime(modulus.as_nz_ref());

// The modular inverse should always exist, because it was ensured odd above, which also ensures it's non-zero
let (inv_mod_limb, inv_mod_limb_exists) = modulus.inv_mod2k_full_vartime(Word::BITS);
Expand Down
6 changes: 3 additions & 3 deletions src/modular/safegcd/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! See parent module for more information.

use super::{Matrix, inv_mod2_62, iterations, jump};
use crate::{BoxedUint, Inverter, Limb, Odd, Word};
use crate::{BoxedUint, Inverter, Limb, Odd, Resize, Word};
use alloc::boxed::Box;
use core::{
cmp::max,
Expand Down Expand Up @@ -34,7 +34,7 @@ impl BoxedSafeGcdInverter {
pub fn new(modulus: &Odd<BoxedUint>, adjuster: &BoxedUint) -> Self {
Self {
modulus: BoxedUnsatInt::from(&modulus.0),
adjuster: BoxedUnsatInt::from(&adjuster.widen(modulus.bits_precision())),
adjuster: BoxedUnsatInt::from(&adjuster.resize(modulus.bits_precision())),
inverse: inv_mod2_62(modulus.0.as_words()),
}
}
Expand Down Expand Up @@ -339,7 +339,7 @@ impl BoxedUnsatInt {

if shorten {
debug_assert!(ret.bits_vartime() <= 32);
ret.shorten(32)
ret.resize(32)
} else {
ret
}
Expand Down
28 changes: 27 additions & 1 deletion src/odd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::{cmp::Ordering, fmt, ops::Deref};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

#[cfg(feature = "alloc")]
use crate::BoxedUint;
use crate::{BoxedUint, Resize};

#[cfg(feature = "rand_core")]
use crate::{Random, rand_core::TryRngCore};
Expand Down Expand Up @@ -150,6 +150,32 @@ impl PartialOrd<Odd<BoxedUint>> for BoxedUint {
}
}

#[cfg(feature = "alloc")]
impl Resize for Odd<BoxedUint> {
type Output = Self;

fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
Odd(self.0.resize_unchecked(at_least_bits_precision))
}

fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
self.0.try_resize(at_least_bits_precision).map(Odd)
}
}

#[cfg(feature = "alloc")]
impl Resize for &Odd<BoxedUint> {
type Output = Odd<BoxedUint>;

fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
Odd((&self.0).resize_unchecked(at_least_bits_precision))
}

fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
(&self.0).try_resize(at_least_bits_precision).map(Odd)
}
}

#[cfg(feature = "rand_core")]
impl<const LIMBS: usize> Random for Odd<Uint<LIMBS>> {
/// Generate a random `Odd<Uint<T>>`.
Expand Down
28 changes: 28 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,34 @@ pub trait ShrVartime: Sized {
fn wrapping_shr_vartime(&self, shift: u32) -> Self;
}

/// Methods for resizing the allocated storage.
pub trait Resize: Sized {
/// The result of the resizing.
type Output;

/// Resizes to the minimum storage that fits `at_least_bits_precision`
/// without checking if the bit size of `self` is larger than `at_least_bits_precision`.
///
/// Variable-time w.r.t. `at_least_bits_precision`.
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output;

/// Resizes to the minimum storage that fits `at_least_bits_precision`
/// returning `None` if the bit size of `self` is larger than `at_least_bits_precision`.
///
/// Variable-time w.r.t. `at_least_bits_precision`.
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output>;

/// Resizes to the minimum storage that fits `at_least_bits_precision`
/// panicking if the bit size of `self` is larger than `at_least_bits_precision`.
///
/// Variable-time w.r.t. `at_least_bits_precision`.
fn resize(self, at_least_bits_precision: u32) -> Self::Output {
self.try_resize(at_least_bits_precision).unwrap_or_else(|| {
panic!("The bit size of `self` is larger than `at_least_bits_precision`")
})
}
}

/// A representation of an integer optimized for the performance of modular operations.
pub trait Monty:
'static
Expand Down
78 changes: 71 additions & 7 deletions src/uint/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod sub_mod;
#[cfg(feature = "rand_core")]
mod rand;

use crate::{Integer, Limb, NonZero, Odd, UintRef, Word, Zero, modular::BoxedMontyForm};
use crate::{Integer, Limb, NonZero, Odd, Resize, UintRef, Word, Zero, modular::BoxedMontyForm};
use alloc::{boxed::Box, vec, vec::Vec};
use core::fmt;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
Expand Down Expand Up @@ -199,6 +199,7 @@ impl BoxedUint {
///
/// Panics if `at_least_bits_precision` is smaller than the current precision.
#[must_use]
#[deprecated(since = "0.7.0", note = "please use `resize` instead")]
pub fn widen(&self, at_least_bits_precision: u32) -> BoxedUint {
assert!(at_least_bits_precision >= self.bits_precision());

Expand All @@ -211,6 +212,7 @@ impl BoxedUint {
///
/// Panics if `at_least_bits_precision` is larger than the current precision.
#[must_use]
#[deprecated(since = "0.7.0", note = "please use `resize` instead")]
pub fn shorten(&self, at_least_bits_precision: u32) -> BoxedUint {
assert!(at_least_bits_precision <= self.bits_precision());
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
Expand Down Expand Up @@ -271,14 +273,76 @@ impl BoxedUint {
limbs[i] = Limb::conditional_select(&limbs[i], &Limb::ZERO, choice);
}
}

/// Returns `true` if the integer's bit size is smaller or equal to `bits`.
pub(crate) fn is_within_bits(&self, bits: u32) -> bool {
bits >= self.bits_precision() || bits >= self.bits()
}
}

impl NonZero<BoxedUint> {
/// Widen this type's precision to the given number of bits.
///
/// See [`BoxedUint::widen`] for more information, including panic conditions.
pub fn widen(&self, bits_precision: u32) -> Self {
NonZero(self.0.widen(bits_precision))
impl Resize for BoxedUint {
type Output = BoxedUint;

fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
let new_len = Self::limbs_for_precision(at_least_bits_precision);
if new_len == self.limbs.len() {
self
} else {
let mut limbs = self.limbs.into_vec();
limbs.resize(new_len, Limb::ZERO);
Self::from(limbs)
}
}

fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
if self.is_within_bits(at_least_bits_precision) {
Some(self.resize_unchecked(at_least_bits_precision))
} else {
None
}
}
}

impl Resize for &BoxedUint {
type Output = BoxedUint;

fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
let num_limbs_to_copy = core::cmp::min(ret.limbs.len(), self.limbs.len());
ret.limbs[..num_limbs_to_copy].copy_from_slice(&self.limbs[..num_limbs_to_copy]);
ret
}

fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
if self.is_within_bits(at_least_bits_precision) {
Some(self.resize_unchecked(at_least_bits_precision))
} else {
None
}
}
}

impl Resize for NonZero<BoxedUint> {
type Output = Self;

fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
NonZero(self.0.resize_unchecked(at_least_bits_precision))
}

fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
self.0.try_resize(at_least_bits_precision).map(NonZero)
}
}

impl Resize for &NonZero<BoxedUint> {
type Output = NonZero<BoxedUint>;

fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
NonZero((&self.0).resize_unchecked(at_least_bits_precision))
}

fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
(&self.0).try_resize(at_least_bits_precision).map(NonZero)
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/uint/boxed/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ impl AddAssign<u128> for BoxedUint {
#[allow(clippy::unwrap_used)]
mod tests {
use super::{BoxedUint, CheckedAdd, Limb};
use crate::Resize;

#[test]
fn adc_no_carry() {
Expand Down Expand Up @@ -267,7 +268,7 @@ mod tests {

#[test]
fn add_assign() {
let mut h = BoxedUint::one().widen(1024);
let mut h = BoxedUint::one().resize(1024);

h += BoxedUint::one();
}
Expand Down
6 changes: 3 additions & 3 deletions src/uint/boxed/gcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Gcd<BoxedUint> for Odd<BoxedUint> {

#[cfg(test)]
mod tests {
use crate::{BoxedUint, Gcd};
use crate::{BoxedUint, Gcd, Resize};

#[test]
fn gcd_relatively_prime() {
Expand Down Expand Up @@ -95,7 +95,7 @@ mod tests {
#[test]
fn gcd_different_sizes() {
// Test that gcd works for boxed Uints with different numbers of limbs
let f = BoxedUint::from(4391633u32).widen(128).to_odd().unwrap();
let f = BoxedUint::from(4391633u32).resize(128).to_odd().unwrap();
let g = BoxedUint::from(2022161u32);
let gcd = f.gcd(&g);
assert_eq!(gcd, BoxedUint::from(1763u32));
Expand All @@ -104,7 +104,7 @@ mod tests {
#[test]
fn gcd_vartime_different_sizes() {
// Test that gcd works for boxed Uints with different numbers of limbs
let f = BoxedUint::from(4391633u32).widen(128).to_odd().unwrap();
let f = BoxedUint::from(4391633u32).resize(128).to_odd().unwrap();
let g = BoxedUint::from(2022161u32);
let gcd = f.gcd_vartime(&g);
assert_eq!(gcd, BoxedUint::from(1763u32));
Expand Down
4 changes: 2 additions & 2 deletions src/uint/boxed/mul.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! [`BoxedUint`] multiplication operations.

use crate::{
BoxedUint, CheckedMul, Limb, WideningMul, Wrapping, WrappingMul, Zero,
BoxedUint, CheckedMul, Limb, Resize, WideningMul, Wrapping, WrappingMul, Zero,
uint::mul::{
karatsuba::{KARATSUBA_MIN_STARTING_LIMBS, karatsuba_mul_limbs, karatsuba_square_limbs},
mul_limbs, square_limbs,
Expand Down Expand Up @@ -33,7 +33,7 @@ impl BoxedUint {

/// Perform wrapping multiplication, wrapping to the width of `self`.
pub fn wrapping_mul(&self, rhs: &Self) -> Self {
self.mul(rhs).shorten(self.bits_precision())
self.mul(rhs).resize_unchecked(self.bits_precision())
}

/// Multiply `self` by itself.
Expand Down
3 changes: 2 additions & 1 deletion src/uint/boxed/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ impl SubAssign<u128> for BoxedUint {
#[allow(clippy::unwrap_used)]
mod tests {
use super::{BoxedUint, CheckedSub, Limb};
use crate::Resize;

#[test]
fn sbb_no_borrow() {
Expand Down Expand Up @@ -276,7 +277,7 @@ mod tests {

#[test]
fn sub_assign() {
let mut h = BoxedUint::one().widen(1024);
let mut h = BoxedUint::one().resize(1024);
h -= BoxedUint::one();
}
}
13 changes: 2 additions & 11 deletions tests/boxed_monty_form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,22 @@ mod common;

use common::to_biguint;
use crypto_bigint::{
BoxedUint, Integer, Inverter, Limb, Odd, PrecomputeInverter,
BoxedUint, Integer, Inverter, Limb, Odd, PrecomputeInverter, Resize,
modular::{BoxedMontyForm, BoxedMontyParams},
};
use num_bigint::BigUint;
use num_integer::Integer as _;
use num_modular::ModularUnaryOps;
use proptest::prelude::*;
use std::cmp::Ordering;

fn retrieve_biguint(monty_form: &BoxedMontyForm) -> BigUint {
to_biguint(&monty_form.retrieve())
}

fn reduce(n: &BoxedUint, p: BoxedMontyParams) -> BoxedMontyForm {
let bits_precision = p.modulus().bits_precision();

let n = match n.bits_precision().cmp(&bits_precision) {
Ordering::Less => n.widen(bits_precision),
Ordering::Equal => n.clone(),
Ordering::Greater => n.shorten(bits_precision),
};

let n_reduced = n
.rem_vartime(p.modulus().as_nz_ref())
.widen(p.bits_precision());
.resize(p.bits_precision());

BoxedMontyForm::new(n_reduced, p)
}
Expand Down
Loading