Libsodium: Ed25519 point-validation bug
A low-level validation function missed a coordinate check, accepting some non-main-subgroup Edwards25519 points. High-level signing APIs remain unaffected; a one-line fix was applied and released.
A tiny missing check let some Edwards25519 points sneak past validation. The fix is one line — but it matters for anyone using low-level point checks.
A low-level validation function missed a coordinate check, accepting some non-main-subgroup Edwards25519 points. High-level signing APIs remain unaffected; a one-line fix was applied and released.
Source: Frank DENIS random thoughts.
Highlights
| Metric | Value | Notes |
|---|---|---|
| Publish date | December 30, 2025 | |
| Affected function | crypto_core_ed25519_is_valid_point() | |
| Root cause | Validation checked X == 0 after multiplying by group order L but omitted verifying Y == Z | |
| Versions affected | Point release ≤ 1.0.20 or libsodium releases before December 30, 2025 | |
| High-level APIs | crypto_sign_* and standard keypair generation are not affected | |
| Fix deployed | Added Y == Z check after multiplication by L | Commit: https://github.com/jedisct1/libsodium/commit/f2da4cd8cb26599a0285a6ab0c02948e361a674a |
Key points
- The function validates whether an Edwards25519 point is in the main subgroup by multiplying by group order L and checking for the identity.
- Old code only tested that X == 0 for the identity representation but did not verify Y == Z, allowing some mixed-order points through.
- Constructing Q + (0, -1) from a main-subgroup point Q produced points that previously passed validation despite not being in the main subgroup.
- High-level signing APIs (crypto_sign_*) and standard keypair generation remain safe and unaffected.
- Support for Ristretto255 (added in 2019) avoids cofactor issues and is the recommended approach for custom arithmetic over the curve.
- A trivial, one-line change adds the missing check; stable packages released after December 30, 2025 include the fix.
- An application-level workaround function (is_on_main_subgroup) is provided for users who cannot immediately upgrade.
Timeline
- 2019 — Ristretto255 support added to libsodium to address cofactor-related issues
- December 30, 2025 — Bug disclosed and fixed; stable packages released after this date include the fix
Why this matters
Low-level point-validation bugs can permit invalid curve points into custom protocols, potentially undermining bespoke cryptography. While mainstream signing APIs are safe, projects using low-level Edwards25519 arithmetic should upgrade or adopt Ristretto255 to avoid cofactor pitfalls. Maintaining secure open-source crypto depends on timely fixes and community support.