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
29 changes: 26 additions & 3 deletions src/uint/modular/constant_mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::{fmt::Debug, marker::PhantomData};

use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

use crate::{Limb, Uint, Zero};

Expand Down Expand Up @@ -87,8 +87,8 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
phantom: PhantomData,
};

/// Instantiates a new `Residue` that represents this `integer` mod `MOD`.
pub const fn new(integer: &Uint<LIMBS>) -> Self {
// Internal helper function to generate a residue; this lets us wrap the constructors more cleanly
const fn generate_residue(integer: &Uint<LIMBS>) -> Self {
let product = integer.mul_wide(&MOD::R2);
let montgomery_form =
montgomery_reduction::<LIMBS>(&product, &MOD::MODULUS, MOD::MOD_NEG_INV);
Expand All @@ -99,6 +99,29 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
}
}

/// Instantiates a new `Residue` that represents this `integer` mod `MOD`.
/// If the modulus represented by `MOD` is not odd, this function will panic; use [`new_checked`][`Residue::new_checked`] if you want to be able to detect an invalid modulus.
pub const fn new(integer: &Uint<LIMBS>) -> Self {
// A valid modulus must be odd
if MOD::MODULUS.ct_is_odd().to_u8() == 0 {
panic!("modulus must be odd");
}

Self::generate_residue(integer)
}

/// Instantiates a new `Residue` that represents this `integer` mod `MOD` if the modulus is odd.
/// Returns a `CtOption` that is `None` if the provided modulus is not odd; this is a safer version of [`new`][`Residue::new`], which can panic.
// TODO: remove this method when we can use `generic_const_exprs.` to ensure the modulus is
// always valid.
pub fn new_checked(integer: &Uint<LIMBS>) -> CtOption<Self> {
// A valid modulus must be odd, which we can check in constant time
CtOption::new(
Self::generate_residue(integer),
MOD::MODULUS.ct_is_odd().into(),
)
}

/// Retrieves the integer currently encoded in this `Residue`, guaranteed to be reduced.
pub const fn retrieve(&self) -> Uint<LIMBS> {
montgomery_reduction::<LIMBS>(
Expand Down
14 changes: 12 additions & 2 deletions src/uint/modular/constant_mod/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#[macro_export]
/// Implements a modulus with the given name, type, and value, in that specific order. Please `use crypto_bigint::traits::Encoding` to make this work.
/// For example, `impl_modulus!(MyModulus, U256, "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");` implements a 256-bit modulus named `MyModulus`.
/// The modulus _must_ be odd, or this will panic.
macro_rules! impl_modulus {
($name:ident, $uint_type:ty, $value:expr) => {
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
Expand All @@ -14,8 +15,16 @@ macro_rules! impl_modulus {
$crate::Concat<Output = $crate::Uint<DLIMBS>>,
{
const LIMBS: usize = { $crate::nlimbs!(<$uint_type>::BITS) };
const MODULUS: $crate::Uint<{ $crate::nlimbs!(<$uint_type>::BITS) }> =
<$uint_type>::from_be_hex($value);
const MODULUS: $crate::Uint<{ $crate::nlimbs!(<$uint_type>::BITS) }> = {
let res = <$uint_type>::from_be_hex($value);

// Check that the modulus is odd
if res.as_limbs()[0].0 & 1 == 0 {
panic!("modulus must be odd");
}

res
};
const R: $crate::Uint<{ $crate::nlimbs!(<$uint_type>::BITS) }> = $crate::Uint::MAX
.const_rem(&Self::MODULUS)
.0
Expand Down Expand Up @@ -43,6 +52,7 @@ macro_rules! impl_modulus {
#[macro_export]
/// Creates a `Residue` with the given value for a specific modulus.
/// For example, `residue!(U256::from(105u64), MyModulus);` creates a `Residue` for 105 mod `MyModulus`.
/// The modulus _must_ be odd, or this will panic.
macro_rules! const_residue {
($variable:ident, $modulus:ident) => {
$crate::modular::constant_mod::Residue::<$modulus, { $modulus::LIMBS }>::new(&$variable)
Expand Down