Skip to content

test(ed25519-verify): add mixed-order strict-parity regression vectors - #9

Merged
zz-sol merged 2 commits into
solana-program:mainfrom
latent-9:fix-cofactorless-verify-strict-torsion
Aug 26, 2026
Merged

zz-sol merged 2 commits into
solana-program:mainfrom
latent-9:fix-cofactorless-verify-strict-torsion

Conversation

@latent-9

@latent-9 latent-9 commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

While fuzzing this crate against ed25519-dalek I found that the cofactorless strict preset disagreed with dalek's verify_strict on signatures where a low-order torsion component is folded into a prime-order public key. The root cause was the runtime scalar negation (L - H): the group order L is odd, so (L - H)*A differs from -(H*A) by L*A, which is only the identity when A has prime order. On a mixed-order key it leaves a non-identity L*T torsion component, so cofactorless verification returned the wrong verdict.

That fix has since landed in main as part of #10, which removes the runtime scalar negation. This PR adds the regression vectors that prove that fix:

  • Two public keys with order-2 and order-4 torsion folded into an otherwise prime-order key.
  • Two signatures that are valid ZIP-215 signatures over the same message, which dalek's verify_strict accepts.
  • The vectors are added to dalek_verify_strict_preset_matches_dalek, which asserts the preset returns the same verdict as dalek.

On the code before #10 the preset rejects these signatures (the bug), and on main it accepts them (fixed). No production code changes.

@latent-9

Copy link
Copy Markdown
Contributor Author

FYI: PR #11 refactors scalar.rs and verifier.rs, the same files this fix touches. Happy to rebase once it lands, or adapt the fix to the refactored code if that helps. Flagging it so the parity fix does not get lost in the refactor.

Fold order-2 and order-4 torsion into prime-order public keys and assert the
cofactorless strict preset agrees with ed25519-dalek's verify_strict on them.

These vectors fail on the code before the runtime scalar negation was removed
(PR #10) and pass on main. The maintainer fix replaces scalar::negate with a
negated basepoint constant; these vectors lock in that parity behavior.
@latent-9
latent-9 force-pushed the fix-cofactorless-verify-strict-torsion branch from a09654c to 06928b6 Compare August 22, 2026 01:44
@latent-9 latent-9 changed the title Fix dalek_verify_strict parity for mixed-order keys test(ed25519-verify): add mixed-order strict-parity regression vectors Aug 22, 2026
@joncinque

Copy link
Copy Markdown

@zz-sol can you take a look?

@joncinque
joncinque requested a review from zz-sol August 26, 2026 09:26
Re-verifies the mixed-order vectors against the refactored verifier:
cargo test workspace-wide green, including dalek_verify_strict_preset_matches_dalek.
@latent-9

Copy link
Copy Markdown
Contributor Author

Merged current main (including the #11 refactor) into this branch and re-ran the suite: cargo test is green workspace-wide, with dalek_verify_strict_preset_matches_dalek still passing on the new mixed-order vectors. No adaptation was needed since the added cases live in the parity test table and touch no error-enum assertions. Ready for review.

@zz-sol zz-sol left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LTGM. Thanks!

@zz-sol
zz-sol merged commit 4d5b842 into solana-program:main Aug 26, 2026
21 checks passed
@latent-9

Copy link
Copy Markdown
Contributor Author

@joncinque @zz-sol thank you for the quick review and for merging this. Being allowed to contribute even a small piece to this ecosystem is appreciated, and thanks to everyone maintaining these crates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants