From 029b6c53a1bb641894ce73340e18bc56bfcf80ce Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Tue, 9 May 2023 04:12:13 -0400 Subject: [PATCH] Use U448 for Ed448 instead of U512 --- crypto/ciphersuite/src/ed448.rs | 4 +--- crypto/ed448/src/backend.rs | 36 ++++++++++++++--------------- crypto/ed448/src/field.rs | 34 ++++++++------------------- crypto/ed448/src/point.rs | 12 ++++------ crypto/ed448/src/scalar.rs | 41 +++++++++++++++------------------ 5 files changed, 52 insertions(+), 75 deletions(-) diff --git a/crypto/ciphersuite/src/ed448.rs b/crypto/ciphersuite/src/ed448.rs index 1c616ec4..8a927251 100644 --- a/crypto/ciphersuite/src/ed448.rs +++ b/crypto/ciphersuite/src/ed448.rs @@ -92,9 +92,7 @@ fn test_ed448() { .unwrap() ) .to_repr() - .iter() - .cloned() - .collect::>(), + .to_vec(), hex::decode( "\ 67a6f023e77361707c6e894c625e809e80f33fdb310810053ae29e28\ diff --git a/crypto/ed448/src/backend.rs b/crypto/ed448/src/backend.rs index b9f17a9b..4b889d94 100644 --- a/crypto/ed448/src/backend.rs +++ b/crypto/ed448/src/backend.rs @@ -94,8 +94,8 @@ macro_rules! field { use $crate::backend::u8_from_bool; - fn reduce(x: U1024) -> U512 { - U512::from_le_slice(&x.rem(&NonZero::new($WIDE_MODULUS).unwrap()).to_le_bytes()[.. 64]) + fn reduce(x: U896) -> U448 { + U448::from_le_slice(&x.rem(&NonZero::new($WIDE_MODULUS).unwrap()).to_le_bytes()[.. 56]) } impl ConstantTimeEq for $FieldName { @@ -117,11 +117,11 @@ macro_rules! field { math_op!($FieldName, $FieldName, Mul, mul, MulAssign, mul_assign, |x: $ResidueType, y| x .mul(&y)); - from_wrapper!($FieldName, U512, u8); - from_wrapper!($FieldName, U512, u16); - from_wrapper!($FieldName, U512, u32); - from_wrapper!($FieldName, U512, u64); - from_wrapper!($FieldName, U512, u128); + from_wrapper!($FieldName, U448, u8); + from_wrapper!($FieldName, U448, u16); + from_wrapper!($FieldName, U448, u32); + from_wrapper!($FieldName, U448, u64); + from_wrapper!($FieldName, U448, u128); impl Neg for $FieldName { type Output = $FieldName; @@ -173,9 +173,9 @@ macro_rules! field { const ONE: Self = Self(Residue::ONE); fn random(mut rng: impl RngCore) -> Self { - let mut bytes = [0; 128]; + let mut bytes = [0; 112]; rng.fill_bytes(&mut bytes); - $FieldName(Residue::new(&reduce(U1024::from_le_slice(bytes.as_ref())))) + $FieldName(Residue::new(&reduce(U896::from_le_slice(bytes.as_ref())))) } fn square(&self) -> Self { @@ -187,13 +187,13 @@ macro_rules! field { fn invert(&self) -> CtOption { const NEG_2: $FieldName = - Self($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U512::from_u8(2)))); + Self($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U448::from_u8(2)))); CtOption::new(self.pow(NEG_2), !self.is_zero()) } fn sqrt(&self) -> CtOption { const MOD_1_4: $FieldName = Self($ResidueType::new( - &$MODULUS.saturating_add(&U512::ONE).wrapping_div(&U512::from_u8(4)), + &$MODULUS.saturating_add(&U448::ONE).wrapping_div(&U448::from_u8(4)), )); let res = self.pow(MOD_1_4); @@ -213,27 +213,27 @@ macro_rules! field { const NUM_BITS: u32 = $NUM_BITS; const CAPACITY: u32 = $NUM_BITS - 1; - const TWO_INV: Self = $FieldName($ResidueType::new(&U512::from_u8(2)).invert().0); + const TWO_INV: Self = $FieldName($ResidueType::new(&U448::from_u8(2)).invert().0); const MULTIPLICATIVE_GENERATOR: Self = - Self(Residue::new(&U512::from_u8($MULTIPLICATIVE_GENERATOR))); + Self(Residue::new(&U448::from_u8($MULTIPLICATIVE_GENERATOR))); // True for both the Ed448 Scalar field and FieldElement field const S: u32 = 1; // Both fields have their root of unity as -1 const ROOT_OF_UNITY: Self = - Self($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U512::ONE))); + Self($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U448::ONE))); const ROOT_OF_UNITY_INV: Self = Self(Self::ROOT_OF_UNITY.0.invert().0); - const DELTA: Self = $FieldName(Residue::new(&U512::from_le_hex($DELTA))); + const DELTA: Self = $FieldName(Residue::new(&U448::from_le_hex($DELTA))); fn from_repr(bytes: Self::Repr) -> CtOption { - let res = U512::from_le_slice(&[bytes.as_ref(), [0; 7].as_ref()].concat()); - CtOption::new($FieldName(Residue::new(&res)), res.ct_lt(&$MODULUS)) + let res = U448::from_le_slice(&bytes[.. 56]); + CtOption::new($FieldName(Residue::new(&res)), res.ct_lt(&$MODULUS) & bytes[56].ct_eq(&0)) } fn to_repr(&self) -> Self::Repr { let mut repr = GenericArray::::default(); - repr.copy_from_slice(&self.0.retrieve().to_le_bytes()[.. 57]); + repr[.. 56].copy_from_slice(&self.0.retrieve().to_le_bytes()); repr } diff --git a/crypto/ed448/src/field.rs b/crypto/ed448/src/field.rs index d74d0987..f14141c7 100644 --- a/crypto/ed448/src/field.rs +++ b/crypto/ed448/src/field.rs @@ -1,18 +1,16 @@ use zeroize::{DefaultIsZeroes, Zeroize}; use crypto_bigint::{ - U512, U1024, + U448, U896, modular::constant_mod::{ResidueParams, Residue}, }; -const MODULUS_PADDED_STR: &str = concat!( - "00000000000000", - "00", +const MODULUS_STR: &str = concat!( "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ); -impl_modulus!(FieldModulus, U512, MODULUS_PADDED_STR); +impl_modulus!(FieldModulus, U448, MODULUS_STR); pub(crate) type ResidueType = Residue; /// Ed448 field element. @@ -21,30 +19,18 @@ pub struct FieldElement(pub(crate) ResidueType); impl DefaultIsZeroes for FieldElement {} -const MODULUS_STR: &str = concat!( - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -); - // 2**448 - 2**224 - 1 -pub(crate) const MODULUS: U512 = U512::from_be_hex(concat!( - "00000000000000", - "00", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -)); +pub(crate) const MODULUS: U448 = U448::from_be_hex(MODULUS_STR); -const WIDE_MODULUS: U1024 = U1024::from_be_hex(concat!( - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "00000000000000", - "00", +const WIDE_MODULUS: U896 = U896::from_be_hex(concat!( + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff" )); pub(crate) const Q_4: FieldElement = FieldElement(ResidueType::new( - &MODULUS.saturating_add(&U512::ONE).wrapping_div(&U512::from_u8(4)), + &MODULUS.saturating_add(&U448::ONE).wrapping_div(&U448::from_u8(4)), )); field!( @@ -56,8 +42,8 @@ field!( 448, 7, concat!( - "3100000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", + "31000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000", ), ); diff --git a/crypto/ed448/src/point.rs b/crypto/ed448/src/point.rs index d67196c9..fa250f90 100644 --- a/crypto/ed448/src/point.rs +++ b/crypto/ed448/src/point.rs @@ -8,7 +8,7 @@ use rand_core::RngCore; use zeroize::Zeroize; use subtle::{Choice, CtOption, ConstantTimeEq, ConditionallySelectable, ConditionallyNegatable}; -use crypto_bigint::{U512, modular::constant_mod::Residue}; +use crypto_bigint::{U448, modular::constant_mod::Residue}; use group::{ ff::{Field, PrimeField, PrimeFieldBits}, @@ -23,18 +23,14 @@ use crate::{ }; const D: FieldElement = - FieldElement(ResidueType::sub(&ResidueType::ZERO, &Residue::new(&U512::from_u16(39081)))); + FieldElement(ResidueType::sub(&ResidueType::ZERO, &Residue::new(&U448::from_u16(39081)))); -const G_Y: FieldElement = FieldElement(Residue::new(&U512::from_be_hex(concat!( - "00000000000000", - "00", +const G_Y: FieldElement = FieldElement(Residue::new(&U448::from_be_hex(concat!( "693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e", "05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14", )))); -const G_X: FieldElement = FieldElement(Residue::new(&U512::from_be_hex(concat!( - "00000000000000", - "00", +const G_X: FieldElement = FieldElement(Residue::new(&U448::from_be_hex(concat!( "4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324", "a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e", )))); diff --git a/crypto/ed448/src/scalar.rs b/crypto/ed448/src/scalar.rs index e5845d87..b0078285 100644 --- a/crypto/ed448/src/scalar.rs +++ b/crypto/ed448/src/scalar.rs @@ -1,18 +1,16 @@ use zeroize::{DefaultIsZeroes, Zeroize}; use crypto_bigint::{ - U512, U1024, + U448, U896, U1024, modular::constant_mod::{ResidueParams, Residue}, }; -const MODULUS_PADDED_STR: &str = concat!( - "00000000000000", - "00", +const MODULUS_STR: &str = concat!( "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3", ); -impl_modulus!(ScalarModulus, U512, MODULUS_PADDED_STR); +impl_modulus!(ScalarModulus, U448, MODULUS_STR); type ResidueType = Residue; /// Ed448 Scalar field element. @@ -21,27 +19,23 @@ pub struct Scalar(pub(crate) ResidueType); impl DefaultIsZeroes for Scalar {} -const MODULUS_STR: &str = concat!( - "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3", -); - // 2**446 - 13818066809895115352007386748515426880336692474882178609894547503885 -pub(crate) const MODULUS: U512 = U512::from_be_hex(concat!( - "00000000000000", - "00", +pub(crate) const MODULUS: U448 = U448::from_be_hex(MODULUS_STR); + +const WIDE_MODULUS: U896 = U896::from_be_hex(concat!( + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000", "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3", )); -const WIDE_MODULUS: U1024 = U1024::from_be_hex(concat!( - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "00000000000000", - "00", +const WIDE_REDUCTION_MODULUS: NonZero = NonZero::from_uint(U1024::from_be_hex(concat!( + "00000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000", "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3", -)); +))); field!( Scalar, @@ -52,15 +46,18 @@ field!( 446, 2, concat!( - "0400000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", + "04000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000", ), ); impl Scalar { /// Perform a wide reduction to obtain a non-biased Scalar. pub fn wide_reduce(bytes: [u8; 114]) -> Scalar { - Scalar(Residue::new(&reduce(U1024::from_le_slice(&[bytes.as_ref(), &[0; 14]].concat())))) + let wide = U1024::from_le_slice(&[bytes.as_ref(), &[0; 14]].concat()); + Scalar(Residue::new(&U448::from_le_slice( + &wide.rem(&WIDE_REDUCTION_MODULUS).to_le_bytes()[.. 56], + ))) } }