Repository navigation
delegation-chain-ref: verify Ed25519 hardening against known edge cases (preventive, no vulnerability) - #138
Merged
Conversation
…es (preventive, no vulnerability found) Preventive self-audit, no external trigger against this repo. Same day, unrelated to us, robertolocatelli81-dev/Noûs found that identity-element Ed25519 keys (R=identity, S=0) forge a signature valid for any message under naive RFC 8032 verification, and that some libraries accept non-canonically-encoded points/scalars (x402-foundation/tsc#4, novifinancial/ed25519-speccheck classes 0 and 11). hop_signature in delegation-chain-ref-v1 is this repo's only LIVE Ed25519 check -- everywhere else (peer-reconciliation-ref-v1's co_signer, anchoring-precedence-ref-v1's admission_invariant) signature validity is a declared, externally-resolved fact, not computed by our own code. This was the one place a weak library would actually matter, and it had never been checked explicitly -- PyNaCl/libsodium being strict was assumed, not verified. Result: no vulnerability. Reproduced, not assumed: - examples/conformance/delegation-chain-ref/small-order-key-vectors.json (small-order-identity-key-universal-forgery-001): a real 2-hop chain through this spec's own hop_signing_preimage(), where hop 1's delegator key IS the identity element and hop_signature IS the textbook universal-forgery signature. Correctly hop_signature_invalid -- confirmed through the repo's own verify_hop_signature(), not an isolated library unit test. verify.py's main() now runs this file too (16/16 total across the whole delegation-chain-ref suite). - examples/conformance/delegation-chain-ref/ed25519-hardening/: the full published novifinancial/ed25519-speccheck suite (Apache-2.0, 12 vectors, vendored verbatim at commit 65519336fda78a3d016e947df6d82848 aca0c9da, byte-verified via git hash-object against the GitHub blob) run against this repo's pinned PyNaCl (requirements.txt). 12/12 match the published LibSodium column exactly: small-order A/R (classes 0-2), out-of-range S (6-7), and non-canonical point encodings for both R and A (8-11, the two classes Noûs named) are all rejected; only the one benign mixed-order edge case every major library accepts (class 3) passes. Documented explicitly in docs/spec/delegation-chain-ref.md as a verified guarantee of the pinned dependency, not of this spec's own logic -- a future PyNaCl/libsodium upgrade or a reimplementation with a different Ed25519 library is not guaranteed to inherit it. check_hardening.py exists to be rerun after any such change. Reproduce: python3 examples/conformance/delegation-chain-ref/verify.py python3 examples/conformance/delegation-chain-ref/ed25519-hardening/check_hardening.py Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Preventive self-audit, no external trigger against this repo. The same day, unrelated to us, robertolocatelli81-dev/Noûs found (
x402-foundation/tsc#4) that identity-element Ed25519 keys (R=identity,S=0) forge a signature valid for any message under naive RFC 8032 verification, and that some libraries accept non-canonically-encoded points/scalars (novifinancial/ed25519-speccheckclasses 0 and 11).hop_signatureindelegation-chain-ref-v1is this repo's only live Ed25519 check — everywhere else (peer-reconciliation-ref-v1'sco_signer,anchoring-precedence-ref-v1'sadmission_invariant) signature validity is a declared, externally-resolved fact, not computed by our own code. This was the one place a weak crypto library would actually matter, and it had never been checked explicitly — "PyNaCl/libsodium is strict" was an assumption, not a verified fact in this repo.Result: no vulnerability found
Reproduced, not assumed:
small-order-key-vectors.json(small-order-identity-key-universal-forgery-001): constructs the real attack inside a real 2-hop chain, through this spec's ownhop_signing_preimage()— hop 1's delegator key is the identity element andhop_signatureis the textbook universal-forgery signature (verifies for any message under the naive equation). Correctlyhop_signature_invalid, confirmed through this repo's ownverify_hop_signature()code path, not an isolated crypto-library unit test.verify.py'smain()now runs this file too — 16/16 across the whole suite.ed25519-hardening/: the full publishednovifinancial/ed25519-specchecksuite (Apache-2.0, 12 vectors, vendored verbatim at commit65519336fda78a3d016e947df6d82848aca0c9da, byte-verified viagit hash-objectagainst the GitHub blob — seeNOTICE.md) run against this repo's pinned PyNaCl (requirements.txt). 12/12 match the published LibSodium column exactly: small-orderA/R(classes 0–2), out-of-rangeS(6–7), and non-canonical point encodings for bothRandA(8–11 — the two classes Noûs named) are all rejected; only the one benign mixed-order edge case every major library accepts (class 3) passes.Documentation
Added explicitly to
docs/spec/delegation-chain-ref.mdas a verified guarantee of the pinned dependency, not of this spec's own logic — a future PyNaCl/libsodium upgrade, or a reimplementation with a different Ed25519 library, is not guaranteed to inherit it.check_hardening.pyexists to be rerun after any such change, not only once.Reproduce
(needs
pip install -r examples/conformance/delegation-chain-ref/requirements.txt)Test plan
verify.py→ 16/16 (12 pre-existing + 4 from other files, now + the new small-order vector)check_hardening.py→ 12/12, matches published LibSodium behavior exactlysmall-order-key-vectors.json's hop 0 (legitimate signer) independently confirmedvalidon its own, confirming the vector's non-attack half is soundcases.jsonverified byte-identical to the source commit viagit hash-object