diff --git a/crypto/evrf/embedwards25519/README.md b/crypto/evrf/embedwards25519/README.md index 5f7f5e47..e282c063 100644 --- a/crypto/evrf/embedwards25519/README.md +++ b/crypto/evrf/embedwards25519/README.md @@ -7,7 +7,7 @@ This curve was found via for finding curves (specifically, curve cycles), modified to search for curves whose field is the Ed25519 scalar field (not the Ed25519 field). -``` +```ignore p = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed q = 0x0fffffffffffffffffffffffffffffffe53f4debb78ff96877063f0306eef96b D = -420435 diff --git a/crypto/evrf/embedwards25519/src/point.rs b/crypto/evrf/embedwards25519/src/point.rs index 9d24e88a..e5a0ba51 100644 --- a/crypto/evrf/embedwards25519/src/point.rs +++ b/crypto/evrf/embedwards25519/src/point.rs @@ -198,6 +198,7 @@ impl Group for Point { Point { x: FieldElement::ZERO, y: FieldElement::ONE, z: FieldElement::ZERO } } fn generator() -> Self { + // Point with the lowest valid x-coordinate Point { x: FieldElement::from_repr(hex_literal::hex!( "0100000000000000000000000000000000000000000000000000000000000000" @@ -335,8 +336,10 @@ impl GroupEncoding for Point { // If this the identity, set y to 1 let y = CtOption::conditional_select(&y, &CtOption::new(FieldElement::ONE, 1.into()), is_identity); + // If this the identity, set y to 1 and z to 0 (instead of 1) + let z = <_>::conditional_select(&FieldElement::ONE, &FieldElement::ZERO, is_identity); // Create the point if we have a y solution - let point = y.map(|y| Point { x, y, z: FieldElement::ONE }); + let point = y.map(|y| Point { x, y, z }); let not_negative_zero = !(is_identity & sign); // Only return the point if it isn't -0 diff --git a/crypto/evrf/secq256k1/src/point.rs b/crypto/evrf/secq256k1/src/point.rs index 384b68c9..b7e51037 100644 --- a/crypto/evrf/secq256k1/src/point.rs +++ b/crypto/evrf/secq256k1/src/point.rs @@ -192,6 +192,7 @@ impl Group for Point { Point { x: FieldElement::ZERO, y: FieldElement::ONE, z: FieldElement::ZERO } } fn generator() -> Self { + // Point with the lowest valid x-coordinate Point { x: FieldElement::from_repr( hex_literal::hex!("0000000000000000000000000000000000000000000000000000000000000001") @@ -334,8 +335,10 @@ impl GroupEncoding for Point { // If this the identity, set y to 1 let y = CtOption::conditional_select(&y, &CtOption::new(FieldElement::ONE, 1.into()), is_identity); + // If this the identity, set y to 1 and z to 0 (instead of 1) + let z = <_>::conditional_select(&FieldElement::ONE, &FieldElement::ZERO, is_identity); // Create the point if we have a y solution - let point = y.map(|y| Point { x, y, z: FieldElement::ONE }); + let point = y.map(|y| Point { x, y, z }); let not_negative_zero = !(is_identity & sign); // Only return the point if it isn't -0 and the sign byte wasn't malleated diff --git a/crypto/ff-group-tests/src/group.rs b/crypto/ff-group-tests/src/group.rs index 0f0aab4e..f2b69acc 100644 --- a/crypto/ff-group-tests/src/group.rs +++ b/crypto/ff-group-tests/src/group.rs @@ -154,18 +154,20 @@ pub fn test_group(rng: &mut R) { /// Test encoding and decoding of group elements. pub fn test_encoding() { - let test = |point: G, msg| { + let test = |point: G, msg| -> G { let bytes = point.to_bytes(); let mut repr = G::Repr::default(); repr.as_mut().copy_from_slice(bytes.as_ref()); - assert_eq!(point, G::from_bytes(&repr).unwrap(), "{msg} couldn't be encoded and decoded"); + let decoded = G::from_bytes(&repr).unwrap(); + assert_eq!(point, decoded, "{msg} couldn't be encoded and decoded"); assert_eq!( point, G::from_bytes_unchecked(&repr).unwrap(), "{msg} couldn't be encoded and decoded", ); + decoded }; - test(G::identity(), "identity"); + assert!(bool::from(test(G::identity(), "identity").is_identity())); test(G::generator(), "generator"); test(G::generator() + G::generator(), "(generator * 2)"); }