mirror of
https://github.com/saymrwulf/anza-cryptography-source.git
synced 2026-09-04 20:24:04 +00:00
improve test coverage (#50)
This commit is contained in:
parent
7cca75ad6e
commit
06cc7111db
4 changed files with 172 additions and 4 deletions
|
|
@ -304,6 +304,28 @@ mod test {
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_checked_wrapper_accepts_full_width_scalars() {
|
||||||
|
let mut a1_bytes = [0u8; 32];
|
||||||
|
a1_bytes[0] = 7;
|
||||||
|
a1_bytes[16] = 1;
|
||||||
|
let a1 = Scalar::from_canonical_bytes(a1_bytes).unwrap();
|
||||||
|
|
||||||
|
let mut a2_bytes = [0u8; 32];
|
||||||
|
a2_bytes[0] = 11;
|
||||||
|
a2_bytes[24] = 1;
|
||||||
|
let a2 = Scalar::from_canonical_bytes(a2_bytes).unwrap();
|
||||||
|
|
||||||
|
let b = random_scalar();
|
||||||
|
let A1 = constants::ED25519_BASEPOINT_POINT * Scalar::from(23u64);
|
||||||
|
let A2 = constants::ED25519_BASEPOINT_POINT * Scalar::from(29u64);
|
||||||
|
|
||||||
|
let result = crate::backend::vartime_triple_base_mul_128_128_256(&a1, &A1, &a2, &A2, &b);
|
||||||
|
let expected = (a1 * A1 + a2 * A2) + b * constants::ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
// Proptest for vartime_triple_scalar_mul_basepoint equivalence
|
// Proptest for vartime_triple_scalar_mul_basepoint equivalence
|
||||||
proptest::proptest! {
|
proptest::proptest! {
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -187,3 +187,50 @@ pub mod spec {
|
||||||
Q.into()
|
Q.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, target_arch = "x86_64"))]
|
||||||
|
mod test {
|
||||||
|
use super::spec_avx2;
|
||||||
|
use crate::backend::serial;
|
||||||
|
use crate::constants;
|
||||||
|
use crate::scalar::Scalar;
|
||||||
|
|
||||||
|
fn scalar_from_low_128(low: [u8; 16]) -> Scalar {
|
||||||
|
let mut bytes = [0u8; 32];
|
||||||
|
bytes[..16].copy_from_slice(&low);
|
||||||
|
Scalar::from_canonical_bytes(bytes).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn avx2_triple_base_matches_serial_and_naive() {
|
||||||
|
if !std::is_x86_feature_detected!("avx2") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let a1 = scalar_from_low_128([
|
||||||
|
0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22,
|
||||||
|
0x11, 0x00,
|
||||||
|
]);
|
||||||
|
let a2 = scalar_from_low_128([
|
||||||
|
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a,
|
||||||
|
0x69, 0x78,
|
||||||
|
]);
|
||||||
|
let b = Scalar::from_bytes_mod_order([
|
||||||
|
0x42, 0x91, 0x0a, 0xbe, 0xef, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
|
||||||
|
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
||||||
|
0x10, 0x20, 0x30, 0x40,
|
||||||
|
]);
|
||||||
|
|
||||||
|
let A1 = constants::ED25519_BASEPOINT_POINT * Scalar::from(31u64);
|
||||||
|
let A2 = constants::ED25519_BASEPOINT_POINT * Scalar::from(37u64);
|
||||||
|
|
||||||
|
let avx2 = spec_avx2::mul_128_128_256_prechecked(&a1, &A1, &a2, &A2, &b);
|
||||||
|
let serial = serial::scalar_mul::vartime_triple_base::mul_128_128_256_prechecked(
|
||||||
|
&a1, &A1, &a2, &A2, &b,
|
||||||
|
);
|
||||||
|
let expected = (a1 * A1 + a2 * A2) + b * constants::ED25519_BASEPOINT_POINT;
|
||||||
|
|
||||||
|
assert_eq!(avx2, serial);
|
||||||
|
assert_eq!(avx2, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::ed_sigs::SigningKey;
|
use crate::constants;
|
||||||
use crate::ed_sigs::VerificationKey;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::ed_sigs::tests::small_order::SMALL_ORDER_SIGS;
|
use crate::ed_sigs::tests::small_order::SMALL_ORDER_SIGS;
|
||||||
|
use crate::ed_sigs::{Error, Signature, SigningKey, VerificationKey};
|
||||||
|
use crate::edwards::CompressedEdwardsY;
|
||||||
|
use crate::scalar::Scalar;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use ed25519::Signature;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_zebra_invalid_signature() {
|
fn test_verify_zebra_invalid_signature() {
|
||||||
|
|
@ -82,6 +82,67 @@ fn test_default_verification_matches_zebra() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_signature_verifier_trait_impl() {
|
||||||
|
let signing_key = SigningKey::from([3u8; 32]);
|
||||||
|
let verification_key = VerificationKey::from(&signing_key);
|
||||||
|
let msg = b"signature::Verifier trait path";
|
||||||
|
let signature = signing_key.sign(msg);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
ed25519::signature::Verifier::verify(&verification_key, msg, &signature).is_ok(),
|
||||||
|
"trait-based verification should accept a valid signature"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
ed25519::signature::Verifier::verify(&verification_key, b"wrong message", &signature)
|
||||||
|
.is_err(),
|
||||||
|
"trait-based verification should reject an invalid signature"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_zebra_prehashed_rejects_noncanonical_s() {
|
||||||
|
let signing_key = SigningKey::from([4u8; 32]);
|
||||||
|
let verification_key = VerificationKey::from(&signing_key);
|
||||||
|
let mut sig_bytes: [u8; 64] = signing_key.sign(b"noncanonical s").into();
|
||||||
|
sig_bytes[32..].copy_from_slice(&constants::BASEPOINT_ORDER.to_bytes());
|
||||||
|
let signature = Signature::from(sig_bytes);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
verification_key.verify_zebra_prehashed(&signature, Scalar::from(1u64)),
|
||||||
|
Err(Error::InvalidSignature)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_zebra_prehashed_rejects_undecodable_r() {
|
||||||
|
let signing_key = SigningKey::from([5u8; 32]);
|
||||||
|
let verification_key = VerificationKey::from(&signing_key);
|
||||||
|
let mut sig_bytes: [u8; 64] = signing_key.sign(b"undecodable r").into();
|
||||||
|
let invalid_r = first_undecodable_r();
|
||||||
|
assert!(CompressedEdwardsY(invalid_r).decompress().is_none());
|
||||||
|
|
||||||
|
sig_bytes[..32].copy_from_slice(&invalid_r);
|
||||||
|
let signature = Signature::from(sig_bytes);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
verification_key.verify_zebra_prehashed(&signature, Scalar::from(1u64)),
|
||||||
|
Err(Error::InvalidSignature)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn first_undecodable_r() -> [u8; 32] {
|
||||||
|
for candidate in 0u16..=u16::MAX {
|
||||||
|
let mut bytes = [0u8; 32];
|
||||||
|
bytes[..2].copy_from_slice(&candidate.to_le_bytes());
|
||||||
|
if CompressedEdwardsY(bytes).decompress().is_none() {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("failed to find an undecodable compressed Edwards-Y encoding");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_dalek_matches_legacy_edge_cases() {
|
fn test_verify_dalek_matches_legacy_edge_cases() {
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,7 @@ mod tests {
|
||||||
use crate::edwards::EdwardsPoint;
|
use crate::edwards::EdwardsPoint;
|
||||||
use crate::field::FieldElement;
|
use crate::field::FieldElement;
|
||||||
use crate::scalar::Scalar;
|
use crate::scalar::Scalar;
|
||||||
|
use crate::traits::Identity;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
fn sw_scalar_mul(point: &SwPoint, scalar: &Scalar) -> SwPoint {
|
fn sw_scalar_mul(point: &SwPoint, scalar: &Scalar) -> SwPoint {
|
||||||
|
|
@ -413,4 +414,41 @@ mod tests {
|
||||||
Some(SwPoint::Identity)
|
Some(SwPoint::Identity)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sw_affine_bytes_round_trip_valid_points() {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
for _ in 0..32 {
|
||||||
|
let scalar = random_scalar(&mut rng);
|
||||||
|
let point = constants::ED25519_BASEPOINT_POINT * scalar;
|
||||||
|
let sw = SwPoint::from_edwards(&point);
|
||||||
|
let encoded = sw.to_affine_le_bytes();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
SwPoint::from_affine_le_bytes(encoded.0, encoded.1),
|
||||||
|
Some(sw)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sw_affine_bytes_reject_off_curve_input() {
|
||||||
|
let x = FieldElement::ZERO.to_bytes();
|
||||||
|
let y = FieldElement::ONE.to_bytes();
|
||||||
|
|
||||||
|
assert!(SwPoint::from_affine_le_bytes(x, y).is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sw_identity_is_additive_neutral_element() {
|
||||||
|
let base = SwPoint::from_edwards(&constants::ED25519_BASEPOINT_POINT);
|
||||||
|
|
||||||
|
assert_eq!(SwPoint::identity().add(&base), base);
|
||||||
|
assert_eq!(base.add(&SwPoint::identity()), base);
|
||||||
|
assert_eq!(
|
||||||
|
SwPoint::identity().to_edwards(),
|
||||||
|
Some(EdwardsPoint::identity())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue