#![cfg(all(feature = "arithmetic", feature = "test-vectors"))]
use elliptic_curve::{
BatchNormalize, Group,
array::Array,
consts::U32,
group::{GroupEncoding, ff::PrimeField},
ops::{LinearCombination, MulByGeneratorVartime, Reduce, ReduceNonZero},
point::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};
test_projective_arithmetic!(
AffinePoint,
ProjectivePoint,
Scalar,
ADD_TEST_VECTORS,
MUL_TEST_VECTORS
);
#[test]
fn projective_identity_to_bytes() {
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(&FieldBytes::from(bytes)))
}
}
prop_compose! {
fn projective()(bytes in any::<[u8; 32]>()) -> ProjectivePoint {
ProjectivePoint::mul_by_generator(&Scalar::reduce(&Array::<u8, U32>::from(bytes)))
}
}
prop_compose! {
fn scalar()(bytes in any::<[u8; 32]>()) -> Scalar {
Scalar::reduce(&Array::<u8, U32>::from(bytes))
}
}
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());
}
}
#[test]
fn lincomb(
p1 in projective(),
s1 in scalar(),
p2 in projective(),
s2 in scalar(),
p3 in projective(),
s3 in scalar(),
) {
let reference = p1 * s1 + p2 * s2 + p3 * s3;
let test = ProjectivePoint::lincomb(&[(p1, s1), (p2, s2), (p3, s3)]);
assert_eq!(reference, test);
}
#[test]
#[cfg(feature = "alloc")]
fn lincomb_alloc(
p1 in projective(),
s1 in scalar(),
p2 in projective(),
s2 in scalar(),
p3 in projective(),
s3 in scalar(),
) {
let reference = p1 * s1 + p2 * s2 + p3 * s3;
let test = ProjectivePoint::lincomb(vec![(p1, s1), (p2, s2), (p3, s3)].as_slice());
assert_eq!(reference, test);
}
#[test]
#[cfg(feature = "alloc")]
fn lincomb_vartime(
p1 in projective(),
s1 in scalar(),
p2 in projective(),
s2 in scalar(),
p3 in projective(),
s3 in scalar(),
) {
let reference = p1 * s1 + p2 * s2 + p3 * s3;
let test = ProjectivePoint::lincomb_vartime(vec![(p1, s1), (p2, s2), (p3, s3)].as_slice());
assert_eq!(reference, test);
}
#[test]
fn mul_by_generator(s1 in scalar()) {
let reference = ProjectivePoint::GENERATOR * s1;
let test = ProjectivePoint::mul_by_generator(&s1);
assert_eq!(reference, test);
}
#[test]
fn mul_by_generator_vartime(s1 in scalar()) {
let reference = ProjectivePoint::GENERATOR * s1;
let test = ProjectivePoint::mul_by_generator_vartime(&s1);
assert_eq!(reference, test);
}
#[test]
fn mul_vartime(
p1 in projective(),
s1 in scalar()
) {
let reference = p1 * s1;
let test = p1.mul_vartime(&s1);
assert_eq!(reference, test);
}
}