Correct decoding identity for embedwards25519/secq256k1

This commit is contained in:
Luke Parker 2025-01-29 23:01:45 -05:00
parent 2bc880e372
commit 315d4fb356
No known key found for this signature in database
4 changed files with 14 additions and 6 deletions
crypto
evrf
embedwards25519
secq256k1/src
ff-group-tests/src

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -154,18 +154,20 @@ pub fn test_group<R: RngCore, G: Group>(rng: &mut R) {
/// Test encoding and decoding of group elements.
pub fn test_encoding<G: PrimeGroup>() {
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)");
}