Skip to content

Add ECVRF-EDWARDS25519-SHA512-TAI VRF implementation per RFC 9381#14

Open
lincolnkerry wants to merge 2 commits into
docs/rockies-v1.0-specfrom
feature/vrf-library
Open

Add ECVRF-EDWARDS25519-SHA512-TAI VRF implementation per RFC 9381#14
lincolnkerry wants to merge 2 commits into
docs/rockies-v1.0-specfrom
feature/vrf-library

Conversation

@lincolnkerry
Copy link
Copy Markdown
Collaborator

Summary

Implements the ECVRF-EDWARDS25519-SHA512-TAI cipher suite (RFC 9381 §5) as mandated by the WorldLand Rockies v.1.0 specification §3. This provides the cryptographic foundation for the VRF-based Verifiable Computation Tree (VCT) consensus mechanism.

Key Changes

  • New crypto/vrf/ecvrf/ package: Pure-Go implementation of RFC 9381 ECVRF-EDWARDS25519-SHA512-TAI, forked from ProtonMail/go-ecvrf (commit dce739d6b120640fb237f6ca18538fd1cefa91c9). Includes:

    • PrivateKey and PublicKey types with Prove() and Verify() methods
    • GenerateKey() for keypair generation from RFC 8032 seeds
    • ProofToHash() helper for extracting VRF output without verification (used by precompile)
    • Full RFC 9381 §B.3 test vector validation (3 vectors, byte-for-byte matching)
  • Typed error handling (spec §8.4): Seven distinct error types (ErrInvalidPrivateKey, ErrInvalidPublicKey, ErrInvalidProofLength, ErrInvalidProofPoint, ErrInvalidProofScalar, ErrInvalidVRFProof, ErrHashToCurveFailed) with ecvrf: prefix for greppability

  • New crypto/vrf/ registry package: Crypto-agility layer that:

    • Defines SchemeID enum (0x01 for ECVRF-EDWARDS25519-SHA512-TAI)
    • Provides Verifier interface for pluggable VRF schemes
    • Implements LookupScheme() dispatcher for header-byte-to-implementation routing
    • Enables future post-quantum VRF additions without modifying core consensus logic
  • Comprehensive test coverage:

    • RFC 9381 §B.3 test vectors (Prove, Verify, GenerateKey, intermediate helpers)
    • Round-trip keygen→prove→verify flow
    • Forgery rejection (all 640 bit-flip positions of proof)
    • Wrong-alpha and wrong-pk rejection
    • Determinism validation
    • Error-path coverage for all typed errors
    • Benchmarks for Prove/Verify operations

Implementation Details

  • Upstream choice: ProtonMail/go-ecvrf (not Algorand's libsodium wrapper) because Algorand implements the incompatible Elligator2 variant (suite 0x04), while spec §3 mandates TAI (suite 0x03)
  • API improvements over upstream:
    • Verify() returns (beta, error) instead of (verified bool, beta, error) to prevent ignoring the bool
    • NewPublicKey() eagerly validates curve membership (rejects malformed keys at construction)
    • Public() returns *PublicKey (cannot fail; key was derived from valid scalar)
    • ProofToHash() exposed as public function for precompile use
  • Constants exposed: ProofSize (80), PublicKeySize (32), BetaSize (64), SeedSize (32), SuiteID (0x03)
  • No cryptographic changes: All curve arithmetic and hash inputs match RFC 9381 exactly; modifications are API/documentation only

Spec References

  • WorldLand Rockies v.1.0 spec §3 (cipher suite selection)
  • §4.1, §4.2 (VCT alpha construction)
  • §4.5 (precompile interface)
  • §8.3 (crypto-agility scheme byte)
  • §8.4 (typed error requirements)
  • §8.7 (upstream provenance)

https://claude.ai/code/session_017MjD1MLyng1WWBG1jcLbGo

claude added 2 commits May 6, 2026 15:18
Transcribes all three RFC 9381 Appendix B.3 test vectors for
ECVRF-EDWARDS25519-SHA512-TAI (sk, pk, alpha, pi, beta, plus the
intermediate x, H, k, U, V values needed to exercise hashToCurveTAI and
the nonce derivation).

Tests added (compilation deliberately fails until the implementation
lands in the next commit; this preserves the TDD red→green discipline
mandated by spec §8.1):

  TestRFC9381_B3_Prove           — proof and beta byte-for-byte
  TestRFC9381_B3_Verify          — verifier accepts and recovers beta
  TestRFC9381_B3_GenerateKey     — RFC 8032 keygen agreement
  TestRFC9381_B3_HashToCurveTAI  — published H values
  TestRFC9381_B3_NonceHash       — published k values
  TestRFC9381_B3_ProofToHash     — standalone helper for precompile path
  TestRoundTrip                  — keygen → prove → verify
  TestVerifyRejectsForgery       — every single-bit flip rejected
  TestVerifyRejects{WrongAlpha,WrongPK} — binding properties
  TestProveDeterministic         — VCT determinism (spec §4.2)
  TestNewPrivateKey_BadLength    — typed ErrInvalidPrivateKey
  TestNewPublicKey_{BadLength,NotOnCurve} — typed ErrInvalidPublicKey
  TestVerify_{BadProofLength,BadGammaPoint,NonCanonicalScalar} — typed
                                   ErrInvalidProofLength / Point / Scalar
  TestProofToHash_{BadLength,BadGamma}
  TestErrorMessages              — every typed error carries 'ecvrf:' prefix
  BenchmarkProve / BenchmarkVerify — spec §5.1 perf budget validation

Spec refs: §4.1, §4.2, §5.1, §8.1, §8.4, §8.7.
Implements the VRF library mandated by Rockies v.1.0 spec §3 and §8.2 (PR 1).
All tests added in the previous (TDD-red) commit now pass, including the
three RFC 9381 §B.3 test vectors byte-for-byte:

  ok  github.com/cryptoecc/WorldLand/crypto/vrf       0.004s   (4 tests)
  ok  github.com/cryptoecc/WorldLand/crypto/vrf/ecvrf 0.114s  (23 tests)

Layout:

  crypto/vrf/
    registry.go       — crypto-agility hub (spec §8.3). SchemeID 0x01
                        dispatches to the TAI suite. Scheme byte is
                        independent of RFC 9381's internal suite_string.
    registry_test.go  — registry dispatch + RFC §B.3 round-trip via the
                        Verifier interface
    ecvrf/
      ecvrf.go        — RFC 9381 §5 algorithm (forked from
                        ProtonMail/go-ecvrf @ dce739d6, MIT)
      errors.go       — typed errors per spec §8.4
      ecvrf_test.go   — RFC §B.3 vectors, forgery sweep, error paths
      UPSTREAM.md     — provenance and modifications from upstream

Modifications from ProtonMail/go-ecvrf upstream (full list in UPSTREAM.md):

  - Verify() returns (beta, err) instead of (verified, beta, err); a
    structurally well-formed but invalid proof now returns
    ErrInvalidVRFProof rather than (false, nil, nil), eliminating the
    "ignore-the-bool" footgun.
  - NewPublicKey() eagerly decodes the curve point so malformed encodings
    are rejected at construction.
  - Public() can no longer fail (it cannot, given a valid privkey).
  - ProofToHash() exposed as a top-level function for the precompile path
    (spec §4.5).
  - Constants ProofSize, PublicKeySize, BetaSize, SeedSize, SuiteID
    exported for downstream layers.
  - Comments reference RFC 9381 sections (not draft-irtf-cfrg-vrf-10).

Performance (Intel Xeon @ 2.10GHz, 4-core):

  BenchmarkProve-4    7645    149548 ns/op
  BenchmarkVerify-4   5935    210646 ns/op

Both well under spec §5.1's <1 ms VRF-verification budget.

Module: adds filippo.io/edwards25519 v1.0.0 as a direct dependency.
go mod tidy also pruned three obsolete go.sum entries (golang.org/x/crypto
v0.0.0-20210921, golang.org/x/mod v0.6.0-dev, golang.org/x/net
v0.0.0-20220607) that were already unreferenced by go.mod.

Spec refs: §3, §4.1, §4.2, §4.5, §5.1, §8.1, §8.2, §8.3, §8.4, §8.7.
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.

2 participants