From 8493dbc7f0057f269f604ea1ef812470e14dc541 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 8 Jun 2025 10:01:23 +0200 Subject: [PATCH 1/2] Update to changes in `BatchNormalize` --- Cargo.lock | 3 +-- Cargo.toml | 3 +++ k256/src/arithmetic/projective.rs | 8 +++--- p256/tests/projective.rs | 44 ++++++++++++++++++++++++++++++- primeorder/src/projective.rs | 12 ++++----- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2432f0b3c..b779ebfab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -416,8 +416,7 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" version = "0.14.0-rc.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "541598dba361b5ba0321caad955ba99ae82a604f4047c4f2743724996abf62f4" +source = "git+https://github.com/RustCrypto/traits#f24c2ae0b6ab6e897fab9645274d5c1d815e671e" dependencies = [ "base16ct", "base64ct", diff --git a/Cargo.toml b/Cargo.toml index 2d57d49d4..071db2023 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,6 @@ opt-level = 2 [patch.crates-io] primefield = { path = "primefield" } primeorder = { path = "primeorder" } + +# https://github.com/RustCrypto/traits/pull/1896 +elliptic-curve = { git = "https://github.com/RustCrypto/traits" } diff --git a/k256/src/arithmetic/projective.rs b/k256/src/arithmetic/projective.rs index 0e1cad2d9..04d8b059b 100644 --- a/k256/src/arithmetic/projective.rs +++ b/k256/src/arithmetic/projective.rs @@ -257,10 +257,10 @@ impl From for ProjectivePoint { } impl BatchNormalize<[ProjectivePoint; N]> for ProjectivePoint { - type Output = [Self::AffineRepr; N]; + type Output = [::AffineRepr; N]; #[inline] - fn batch_normalize(points: &[Self; N]) -> [Self::AffineRepr; N] { + fn batch_normalize(points: &[Self; N]) -> [::AffineRepr; N] { let zs = [FieldElement::ONE; N]; let mut affine_points = [AffinePoint::IDENTITY; N]; batch_normalize_generic(points, zs, &mut affine_points); @@ -270,10 +270,10 @@ impl BatchNormalize<[ProjectivePoint; N]> for ProjectivePoint { #[cfg(feature = "alloc")] impl BatchNormalize<[ProjectivePoint]> for ProjectivePoint { - type Output = Vec; + type Output = Vec<::AffineRepr>; #[inline] - fn batch_normalize(points: &[Self]) -> Vec { + fn batch_normalize(points: &[Self]) -> Vec<::AffineRepr> { let zs = vec![FieldElement::ONE; points.len()]; let mut affine_points = vec![AffinePoint::IDENTITY; points.len()]; batch_normalize_generic(points, zs, &mut affine_points); diff --git a/p256/tests/projective.rs b/p256/tests/projective.rs index e57808cbd..0044a3e8f 100644 --- a/p256/tests/projective.rs +++ b/p256/tests/projective.rs @@ -3,14 +3,18 @@ #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] use elliptic_curve::{ + BatchNormalize, group::{GroupEncoding, ff::PrimeField}, + ops::ReduceNonZero, + point::NonIdentity, sec1::{self, ToEncodedPoint}, }; use p256::{ - AffinePoint, ProjectivePoint, Scalar, + AffinePoint, NonZeroScalar, ProjectivePoint, Scalar, test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS}, }; use primeorder::{Double, test_projective_arithmetic}; +use proptest::{prelude::any, prop_compose, proptest}; test_projective_arithmetic!( AffinePoint, @@ -25,3 +29,41 @@ fn projective_identity_to_bytes() { // This is technically an invalid SEC1 encoding, but is preferable to panicking. assert_eq!([0; 33], ProjectivePoint::IDENTITY.to_bytes().as_slice()); } + +prop_compose! { + fn non_identity()(bytes in any::<[u8; 32]>()) -> NonIdentity { + NonIdentity::mul_by_generator(&NonZeroScalar::reduce_nonzero_bytes(&bytes.into())) + } +} + +// TODO: move to `primeorder::test_projective_arithmetic`. +proptest! { + #[test] + fn batch_normalize( + a in non_identity(), + b in non_identity(), + ) { + let points: [NonIdentity; 2] = [a, b]; + + let affine_points = NonIdentity::batch_normalize(&points); + + for (point, affine_point) in points.into_iter().zip(affine_points) { + assert_eq!(affine_point, point.to_affine()); + } + } + + #[test] + #[cfg(feature = "alloc")] + fn batch_normalize_alloc( + a in non_identity(), + b in non_identity(), + ) { + let points = vec![a, b]; + + let affine_points = NonIdentity::batch_normalize(points.as_slice()); + + for (point, affine_point) in points.into_iter().zip(affine_points) { + assert_eq!(affine_point, point.to_affine()); + } + } +} diff --git a/primeorder/src/projective.rs b/primeorder/src/projective.rs index b4419a0c6..46d179477 100644 --- a/primeorder/src/projective.rs +++ b/primeorder/src/projective.rs @@ -13,7 +13,7 @@ use elliptic_curve::{ array::ArraySize, bigint::ArrayEncoding, group::{ - self, Group, GroupEncoding, + Curve, Group, GroupEncoding, prime::{PrimeCurve, PrimeGroup}, }, ops::{BatchInvert, LinearCombination}, @@ -308,7 +308,7 @@ where } } -impl group::Curve for ProjectivePoint +impl Curve for ProjectivePoint where Self: Double, C: PrimeCurveParams, @@ -333,10 +333,10 @@ where Self: Double, C: PrimeCurveParams, { - type Output = [Self::AffineRepr; N]; + type Output = [::AffineRepr; N]; #[inline] - fn batch_normalize(points: &[Self; N]) -> [Self::AffineRepr; N] { + fn batch_normalize(points: &[Self; N]) -> [::AffineRepr; N] { let zs = [C::FieldElement::ONE; N]; let mut affine_points = [C::AffinePoint::IDENTITY; N]; batch_normalize_generic(points, zs, &mut affine_points); @@ -350,10 +350,10 @@ where Self: Double, C: PrimeCurveParams, { - type Output = Vec; + type Output = Vec<::AffineRepr>; #[inline] - fn batch_normalize(points: &[Self]) -> Vec { + fn batch_normalize(points: &[Self]) -> Vec<::AffineRepr> { let mut zs = vec![C::FieldElement::ONE; points.len()]; let mut affine_points = vec![AffinePoint::IDENTITY; points.len()]; batch_normalize_generic(points, zs.as_mut_slice(), &mut affine_points); From e92ceec6d04b1ca55801c4e9239c09194de92431 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Fri, 13 Jun 2025 22:18:24 +0200 Subject: [PATCH 2/2] Update to hash2curve changes --- Cargo.lock | 2 +- Cargo.toml | 1 + ed448-goldilocks/src/curve/edwards/extended.rs | 4 ++-- ed448-goldilocks/src/decaf/points.rs | 2 +- ed448-goldilocks/src/field/scalar.rs | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b779ebfab..a4141817f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -416,7 +416,7 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" version = "0.14.0-rc.5" -source = "git+https://github.com/RustCrypto/traits#f24c2ae0b6ab6e897fab9645274d5c1d815e671e" +source = "git+https://github.com/RustCrypto/traits#0eab8e247bcf0746a51215147c357e52b1f32f46" dependencies = [ "base16ct", "base64ct", diff --git a/Cargo.toml b/Cargo.toml index 071db2023..e0edfc65c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,4 +24,5 @@ primefield = { path = "primefield" } primeorder = { path = "primeorder" } # https://github.com/RustCrypto/traits/pull/1896 +# https://github.com/RustCrypto/traits/pull/1901 elliptic-curve = { git = "https://github.com/RustCrypto/traits" } diff --git a/ed448-goldilocks/src/curve/edwards/extended.rs b/ed448-goldilocks/src/curve/edwards/extended.rs index f9c708d11..dd9c7dc98 100644 --- a/ed448-goldilocks/src/curve/edwards/extended.rs +++ b/ed448-goldilocks/src/curve/edwards/extended.rs @@ -751,7 +751,7 @@ impl EdwardsPoint { let mut expander = X::expand_message( &[msg], &dst, - core::num::NonZero::new(RandomLen::USIZE * 2) + core::num::NonZero::new(RandomLen::U16 * 2) .expect("invariant violation: random is non zero length"), ) .expect("bad dst"); @@ -788,7 +788,7 @@ impl EdwardsPoint { let mut expander = X::expand_message( &[msg], &dst, - core::num::NonZero::new(RandomLen::USIZE) + core::num::NonZero::new(RandomLen::U16) .expect("invariant violation: random is non zero length"), ) .expect("bad dst"); diff --git a/ed448-goldilocks/src/decaf/points.rs b/ed448-goldilocks/src/decaf/points.rs index 32ffabc08..e7be4e031 100644 --- a/ed448-goldilocks/src/decaf/points.rs +++ b/ed448-goldilocks/src/decaf/points.rs @@ -363,7 +363,7 @@ impl DecafPoint { let mut expander = X::expand_message( &[msg], &dst, - core::num::NonZero::new(RandomLen::USIZE * 2) + core::num::NonZero::new(RandomLen::U16 * 2) .expect("invariant violation: random is non zero length"), ) .expect("bad dst"); diff --git a/ed448-goldilocks/src/field/scalar.rs b/ed448-goldilocks/src/field/scalar.rs index e5a960e85..e037cb1cd 100644 --- a/ed448-goldilocks/src/field/scalar.rs +++ b/ed448-goldilocks/src/field/scalar.rs @@ -858,7 +858,7 @@ impl Scalar { let mut expander = X::expand_message( &[msg], &dst, - core::num::NonZero::new(RandomLen::USIZE).expect("Invariant violation"), + core::num::NonZero::new(RandomLen::U16).expect("Invariant violation"), ) .expect("invalid dst"); expander.fill_bytes(&mut random_bytes);