From cdf107f094211075027ad3059b699853f631f3d6 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Wed, 1 Nov 2023 14:53:15 -0600 Subject: [PATCH] fix 32-bit mode, faster reduce wide Signed-off-by: Michael Lodder --- .../src/backend/serial/fiat_u32/field.rs | 12 ++++++-- .../src/backend/serial/fiat_u64/field.rs | 10 +++++++ .../src/backend/serial/u32/field.rs | 12 ++++++-- .../src/backend/serial/u64/field.rs | 10 +++++++ curve25519-dalek/src/edwards.rs | 29 ++++--------------- curve25519-dalek/src/field.rs | 23 +++++++++++++++ 6 files changed, 68 insertions(+), 28 deletions(-) diff --git a/curve25519-dalek/src/backend/serial/fiat_u32/field.rs b/curve25519-dalek/src/backend/serial/fiat_u32/field.rs index fc19badbd..6c8d0f253 100644 --- a/curve25519-dalek/src/backend/serial/fiat_u32/field.rs +++ b/curve25519-dalek/src/backend/serial/fiat_u32/field.rs @@ -198,9 +198,17 @@ impl FieldElement2625 { FieldElement2625::from_limbs([486662, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// Elligator2 constant for Edwards Curve pub const EDWARDS_MINUS_ELL_A: FieldElement2625 = FieldElement2625::from_limbs([ - 0xfff892e7, 0x7ffff, 0xffffffff, 0x7ffff, 0xffffffff, 0x7ffff, 0xffffffff, 0x7ffff, - 0xffffffff, 0x7ffff, + 0x03f892e7, 0x01ffffff, 0x03ffffff, 0x01ffffff, 0x03ffffff, 0x01ffffff, 0x03ffffff, + 0x01ffffff, 0x03ffffff, 0x01ffffff, ]); + /// 1/sqrt(D) used for converting a montgomery point to edwards + pub const MONTGOMERY_TO_EDWARDS_INV_SQRT_D: FieldElement2625 = FieldElement2625::from_limbs([ + 0x03457e06, 0x01812abf, 0x0350598d, 0x08a5be8, 0x0316874f, 0x01fc4f7e, 0x01846e01, + 0x00d77a4f, 0x03460a00, 0x003c9bb7, + ]); + /// 2^192 + pub const F_2_192: FieldElement2625 = + FieldElement2625::from_limbs([0, 0, 0, 0, 0, 0, 0, 0x2000, 0, 0]); /// The scalar \\( 0 \\). pub const ZERO: FieldElement2625 = FieldElement2625::from_limbs([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// The scalar \\( 1 \\). diff --git a/curve25519-dalek/src/backend/serial/fiat_u64/field.rs b/curve25519-dalek/src/backend/serial/fiat_u64/field.rs index 3b11b7fbc..8915d1aa5 100644 --- a/curve25519-dalek/src/backend/serial/fiat_u64/field.rs +++ b/curve25519-dalek/src/backend/serial/fiat_u64/field.rs @@ -182,6 +182,16 @@ impl FieldElement51 { 0x7ffffffffffff, 0x7ffffffffffff, ]); + /// 1/sqrt(D) used for converting a montgomery point to edwards + pub const MONTGOMERY_TO_EDWARDS_INV_SQRT_D: FieldElement51 = FieldElement51::from_limbs([ + 0x604aaff457e06, + 0x2296fa350598d, + 0x7f13dfb16874f, + 0x35de93d846e01, + 0x0f26edf460a00, + ]); + /// 2^192 + pub const F_2_192: FieldElement51 = FieldElement51::from_limbs([0, 0, 0, 0x0008000000000, 0]); /// The scalar \\( 0 \\). pub const ZERO: FieldElement51 = FieldElement51::from_limbs([0, 0, 0, 0, 0]); /// The scalar \\( 1 \\). diff --git a/curve25519-dalek/src/backend/serial/u32/field.rs b/curve25519-dalek/src/backend/serial/u32/field.rs index 6929bccef..f6d433a97 100644 --- a/curve25519-dalek/src/backend/serial/u32/field.rs +++ b/curve25519-dalek/src/backend/serial/u32/field.rs @@ -293,9 +293,17 @@ impl FieldElement2625 { FieldElement2625::from_limbs([486662, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// Elligator2 constant for Edwards Curve pub const EDWARDS_MINUS_ELL_A: FieldElement2625 = FieldElement2625::from_limbs([ - 0xfff892e7, 0x7ffff, 0xffffffff, 0x7ffff, 0xffffffff, 0x7ffff, 0xffffffff, 0x7ffff, - 0xffffffff, 0x7ffff, + 0x03f892e7, 0x01ffffff, 0x03ffffff, 0x01ffffff, 0x03ffffff, 0x01ffffff, 0x03ffffff, + 0x01ffffff, 0x03ffffff, 0x01ffffff, ]); + /// 1/sqrt(D) used for converting a montgomery point to edwards + pub const MONTGOMERY_TO_EDWARDS_INV_SQRT_D: FieldElement2625 = FieldElement2625::from_limbs([ + 0x03457e06, 0x01812abf, 0x0350598d, 0x08a5be8, 0x0316874f, 0x01fc4f7e, 0x01846e01, + 0x00d77a4f, 0x03460a00, 0x003c9bb7, + ]); + /// 2^192 + pub const F_2_192: FieldElement2625 = + FieldElement2625::from_limbs([0, 0, 0, 0, 0, 0, 0, 0x2000, 0, 0]); /// The scalar \\( 0 \\). pub const ZERO: FieldElement2625 = FieldElement2625::from_limbs([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// The scalar \\( 1 \\). diff --git a/curve25519-dalek/src/backend/serial/u64/field.rs b/curve25519-dalek/src/backend/serial/u64/field.rs index 3b35e570e..b1b130510 100644 --- a/curve25519-dalek/src/backend/serial/u64/field.rs +++ b/curve25519-dalek/src/backend/serial/u64/field.rs @@ -269,6 +269,16 @@ impl FieldElement51 { 0x7ffffffffffff, 0x7ffffffffffff, ]); + /// 1/sqrt(D) used for converting a montgomery point to edwards + pub const MONTGOMERY_TO_EDWARDS_INV_SQRT_D: FieldElement51 = FieldElement51::from_limbs([ + 0x604aaff457e06, + 0x2296fa350598d, + 0x7f13dfb16874f, + 0x35de93d846e01, + 0x0f26edf460a00, + ]); + /// 2^192 + pub const F_2_192: FieldElement51 = FieldElement51::from_limbs([0, 0, 0, 0x0008000000000, 0]); /// The scalar \\( 0 \\). pub const ZERO: FieldElement51 = FieldElement51::from_limbs([0, 0, 0, 0, 0]); /// The scalar \\( 1 \\). diff --git a/curve25519-dalek/src/edwards.rs b/curve25519-dalek/src/edwards.rs index 6328947bb..d52fa456e 100644 --- a/curve25519-dalek/src/edwards.rs +++ b/curve25519-dalek/src/edwards.rs @@ -613,10 +613,7 @@ impl EdwardsPoint { where X: for<'a> elliptic_curve::hash2curve::ExpandMsg<'a>, { - use elliptic_curve::{ - bigint::{ArrayEncoding, Encoding, NonZero, U384}, - hash2curve::Expander, - }; + use elliptic_curve::hash2curve::Expander; let dst = [dst]; let mut random_bytes = [0u8; 96]; @@ -624,19 +621,8 @@ impl EdwardsPoint { X::expand_message(&[msg], &dst, random_bytes.len()).expect("expand_message failed"); expander.fill_bytes(&mut random_bytes); - let p = NonZero::new(U384::from_be_hex("000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed")).expect("NonZero::new failed"); - let u0 = U384::from_be_bytes( - <[u8; 48]>::try_from(&random_bytes[..48]).expect("try_from failed"), - ) % p; - let u1 = U384::from_be_bytes( - <[u8; 48]>::try_from(&random_bytes[48..]).expect("try_from failed"), - ) % p; - - let mut arr = [0u8; 32]; - arr.copy_from_slice(&u0.to_le_byte_array()[..32]); - let u0 = FieldElement::from_bytes(&arr); - arr.copy_from_slice(&u1.to_le_byte_array()[..32]); - let u1 = FieldElement::from_bytes(&arr); + let u0 = FieldElement::from_xmd_bytes_mod_order(&random_bytes[..48]); + let u1 = FieldElement::from_xmd_bytes_mod_order(&random_bytes[48..]); let q0 = map_to_edwards(u0); let q1 = map_to_edwards(u1); @@ -674,11 +660,7 @@ fn elligator_encode(e: FieldElement) -> (FieldElement, FieldElement) { #[cfg(feature = "group")] fn montgomery_to_edwards(u: FieldElement, v: FieldElement) -> (FieldElement, FieldElement) { - let inv_sqr_d = FieldElement::from_bytes(&[ - 6, 126, 69, 255, 170, 4, 110, 204, 130, 26, 125, 75, 209, 211, 161, 197, 126, 79, 252, 3, - 220, 8, 123, 210, 187, 6, 160, 96, 244, 237, 38, 15, - ]); - let x = &(&v.invert() * &u) * &inv_sqr_d; + let x = &(&v.invert() * &u) * &FieldElement::MONTGOMERY_TO_EDWARDS_INV_SQRT_D; let u1 = &u - &FieldElement::ONE; let u2 = &u + &FieldElement::ONE; let y = &u1 * &u2.invert(); @@ -687,12 +669,11 @@ fn montgomery_to_edwards(u: FieldElement, v: FieldElement) -> (FieldElement, Fie #[cfg(feature = "group")] fn affine_to_edwards(x: FieldElement, y: FieldElement) -> EdwardsPoint { - let t = &x * &y; EdwardsPoint { X: x, Y: y, Z: FieldElement::ONE, - T: t, + T: &x * &y, } } diff --git a/curve25519-dalek/src/field.rs b/curve25519-dalek/src/field.rs index 87058941e..290d0d5db 100644 --- a/curve25519-dalek/src/field.rs +++ b/curve25519-dalek/src/field.rs @@ -305,6 +305,29 @@ impl FieldElement { pub(crate) fn invsqrt(&self) -> (Choice, FieldElement) { FieldElement::sqrt_ratio_i(&FieldElement::ONE, self) } + + /// Handle 48 bytes like a big integer and reduce mod order + /// i.e. big_int(48 bytes) % p + /// but without using any reduce methods + pub(crate) fn from_xmd_bytes_mod_order(bytes: &[u8]) -> FieldElement { + assert_eq!(bytes.len(), 48); + // XMD output is expected to be big endian but FieldElement51 + // expects bytes to be little endian. + // Break the array in half with the 1st half as the hi value + // and the 2nd half as the lo value + let mut arr = [0u8; 32]; + for i in 0..24 { + arr[i] = bytes[23-i]; + } + let mut hi = FieldElement::from_bytes(&arr); + for i in 0..24 { + arr[i] = bytes[47-i]; + } + let lo = FieldElement::from_bytes(&arr); + hi *= &FieldElement::F_2_192; + &hi + &lo + } + } #[cfg(test)]