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
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ opt-level = 2
[patch.crates-io]
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" }
4 changes: 2 additions & 2 deletions ed448-goldilocks/src/curve/edwards/extended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion ed448-goldilocks/src/decaf/points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion ed448-goldilocks/src/field/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions k256/src/arithmetic/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,10 @@ impl From<AffinePoint> for ProjectivePoint {
}

impl<const N: usize> BatchNormalize<[ProjectivePoint; N]> for ProjectivePoint {
type Output = [Self::AffineRepr; N];
type Output = [<Self as Curve>::AffineRepr; N];

#[inline]
fn batch_normalize(points: &[Self; N]) -> [Self::AffineRepr; N] {
fn batch_normalize(points: &[Self; N]) -> [<Self as Curve>::AffineRepr; N] {
let zs = [FieldElement::ONE; N];
let mut affine_points = [AffinePoint::IDENTITY; N];
batch_normalize_generic(points, zs, &mut affine_points);
Expand All @@ -270,10 +270,10 @@ impl<const N: usize> BatchNormalize<[ProjectivePoint; N]> for ProjectivePoint {

#[cfg(feature = "alloc")]
impl BatchNormalize<[ProjectivePoint]> for ProjectivePoint {
type Output = Vec<Self::AffineRepr>;
type Output = Vec<<Self as Curve>::AffineRepr>;

#[inline]
fn batch_normalize(points: &[Self]) -> Vec<Self::AffineRepr> {
fn batch_normalize(points: &[Self]) -> Vec<<Self as Curve>::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);
Expand Down
44 changes: 43 additions & 1 deletion p256/tests/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<ProjectivePoint> {
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<ProjectivePoint>; 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());
}
}
}
12 changes: 6 additions & 6 deletions primeorder/src/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use elliptic_curve::{
array::ArraySize,
bigint::ArrayEncoding,
group::{
self, Group, GroupEncoding,
Curve, Group, GroupEncoding,
prime::{PrimeCurve, PrimeGroup},
},
ops::{BatchInvert, LinearCombination},
Expand Down Expand Up @@ -308,7 +308,7 @@ where
}
}

impl<C> group::Curve for ProjectivePoint<C>
impl<C> Curve for ProjectivePoint<C>
Copy link
Member

@tarcieri tarcieri Jun 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used group::Curve intentionally to keep it namespaced since Curve is incredibly overloaded (really it should probably be named CurveGroup, see zkcrypto/group#51).

I guess elliptic-curve could re-export it as CurveGroup.

All that said, I guess this is fine for now and I'll follow up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, apologies. I was importing it to be able to use it. But I can just import it as use ...::Curve as _.

Let me know if you want me to fix this up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can fix it up after this: RustCrypto/traits#1902

where
Self: Double,
C: PrimeCurveParams,
Expand All @@ -333,10 +333,10 @@ where
Self: Double,
C: PrimeCurveParams,
{
type Output = [Self::AffineRepr; N];
type Output = [<Self as Curve>::AffineRepr; N];

#[inline]
fn batch_normalize(points: &[Self; N]) -> [Self::AffineRepr; N] {
fn batch_normalize(points: &[Self; N]) -> [<Self as Curve>::AffineRepr; N] {
let zs = [C::FieldElement::ONE; N];
let mut affine_points = [C::AffinePoint::IDENTITY; N];
batch_normalize_generic(points, zs, &mut affine_points);
Expand All @@ -350,10 +350,10 @@ where
Self: Double,
C: PrimeCurveParams,
{
type Output = Vec<Self::AffineRepr>;
type Output = Vec<<Self as Curve>::AffineRepr>;

#[inline]
fn batch_normalize(points: &[Self]) -> Vec<Self::AffineRepr> {
fn batch_normalize(points: &[Self]) -> Vec<<Self as Curve>::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);
Expand Down