Skip to content
Closed
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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ ed448-goldilocks = { path = "ed448-goldilocks" }
hash2curve = { path = "hash2curve" }
primefield = { path = "primefield" }
primeorder = { path = "primeorder" }

#rustcrypto-group = { git = "https://github.com/RustCrypto/group", branch = "dense-wnaf" }
8 changes: 8 additions & 0 deletions p256/tests/projective.proptest-regressions
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc e19ee42c127b7289fbe7e42df47abf141eb644afcbd13ac141e39b9960362174 # shrinks to point = ProjectivePoint { x: FieldElement(0x823CD15F6DD3C71933565064513A6B2BD183E554C6A08622F713EBBBFACE98BE), y: FieldElement(0x55DF5D5850F47BAD82149139979369FE498A9022A412B5E0BEDD2CFC21C3ED91), z: FieldElement(0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5) }, scalar = Scalar(0x0000000000000000000000000000000000000000000000000000000000000001)
cc 67d76546dee30db7f75f666ed335f84d90da4ce8775d612dcdb88a3058ef7071 # shrinks to point = ProjectivePoint { x: FieldElement(0x823CD15F6DD3C71933565064513A6B2BD183E554C6A08622F713EBBBFACE98BE), y: FieldElement(0x55DF5D5850F47BAD82149139979369FE498A9022A412B5E0BEDD2CFC21C3ED91), z: FieldElement(0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5) }, scalar = Scalar(0xAE74000000000000000000000000000000000000000000000000000000000000)
38 changes: 36 additions & 2 deletions p256/tests/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ use elliptic_curve::{
consts::U32,
group::{GroupEncoding, ff::PrimeField},
ops::{LinearCombination, Reduce, ReduceNonZero},
point::NonIdentity,
point::{AffineCoordinates, NonIdentity},
sec1::{self, ToSec1Point},
};
use p256::{
AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, Scalar,
test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS},
};
use primeorder::test_projective_arithmetic;
use proptest::{prelude::any, prop_compose, proptest};
use proptest::{prelude::*, prop_compose, proptest};

#[cfg(feature = "alloc")]
use elliptic_curve::group::Wnaf;

test_projective_arithmetic!(
AffinePoint,
Expand All @@ -26,6 +29,26 @@ test_projective_arithmetic!(
MUL_TEST_VECTORS
);

#[cfg(feature = "alloc")]
#[test]
fn wnaf() {
for (k, coords) in ADD_TEST_VECTORS.iter().enumerate() {
let scalar = Scalar::from(k as u64 + 1);
dbg!(&scalar, coords);

let mut wnaf = Wnaf::new();
let p = wnaf
.scalar(&scalar)
.base(ProjectivePoint::GENERATOR)
.to_affine();
// let mut wnaf_base = wnaf.base(ProjectivePoint::GENERATOR, 1);
// let p = wnaf_base.scalar(&scalar).to_affine();

let (x, _y) = (p.x(), p.y());
assert_eq!(x.0, coords.0);
}
}

#[test]
fn projective_identity_to_bytes() {
// This is technically an invalid SEC1 encoding, but is preferable to panicking.
Expand All @@ -52,6 +75,17 @@ prop_compose! {

// TODO: move to `primeorder::test_projective_arithmetic`.
proptest! {
#[cfg(feature = "alloc")]
#[test]
fn wnaf_proptest(
point in projective(),
scalar in scalar(),
) {
let result = point * scalar;
let wnaf_result = Wnaf::new().scalar(&scalar).base(point);
prop_assert_eq!(result.to_affine(), wnaf_result.to_affine());
}

#[test]
fn batch_normalize(
a in non_identity(),
Expand Down
31 changes: 30 additions & 1 deletion primeorder/src/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use elliptic_curve::{
};

#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use {alloc::vec::Vec, elliptic_curve::group::WnafGroup};

#[cfg(feature = "serde")]
use serdect::serde::{Deserialize, Serialize, de, ser};
Expand Down Expand Up @@ -598,6 +598,35 @@ where
}
}

#[cfg(feature = "alloc")]
impl<C> WnafGroup for ProjectivePoint<C>
where
C: PrimeCurveParams,
FieldBytes<C>: Copy,
{
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
// Empirical heuristic from the zcash/bellman implementation.
if num_scalars >= 32 {
3
} else if num_scalars >= 1 {
2
} else {
4
}
}

fn scalar_repr_to_le_bytes(
repr: &<Scalar<C> as PrimeField>::Repr,
) -> Vec<u8> {
// SEC1/NIST curves use big-endian scalar representations;
// reverse to get little-endian for wNAF decomposition.
let mut le: Vec<u8> =
AsRef::<[u8]>::as_ref(repr).to_vec();
le.reverse();
le
}
}

//
// `core::ops` trait impls
//
Expand Down
Loading