Formally verified ed25519 (upstream curve25519-dalek v5): field + complete Edwards addition law proven in Lean 4 via Charon/Aeneas; axiom-audited certificates
Find a file
mrwulf 33fb8bb231 Coherence pass 4 (the closing pass): 4-tier apex documentation + hygiene
- README: pyramid-diagram apex row upgraded to the proven full lift
  (accepted <=> decompress(R) = [k](-A)+[s]B), status table names all
  four button-enforced tiers, apex section gains the phase-2 tier table
  (half-lift / point equation / full lift) + the decompress-chain
  summary; source pin updated to the pushed patch commit.
- TRUSTED-BASE item 5: rewritten from the single byte-apex certificate
  to the FOUR enforced tiers (decompress_of_canonical noted as
  standard-three-only).
- gen/CurveField/FunsExternal.lean: stale root-namespace
  edwards.decompress.step_1/step_2 axioms removed (dead weight left
  behind by un-opaquing; outside every cone, but they forced
  fully-qualified unfolds - see control FAILURES.md).
- check.sh Phase 3b success echo aligned to "apex + full-lift" (echo
  only; the enforcing greps covered all four tiers already).

Validated by the pass-4 sweep: 9/9 buttons green (this repo's check.sh
+ check-scalar.sh among them), logs retained in the pass workspace.
Full record: formal-verification-control/COHERENCE-PASS-4.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 04:01:15 +02:00
verification Coherence pass 4 (the closing pass): 4-tier apex documentation + hygiene 2026-07-06 04:01:15 +02:00
.gitignore skeleton: proof-pyramid layout, honest status table, trusted-base doc 2026-07-02 13:10:26 +02:00
README.md Coherence pass 4 (the closing pass): 4-tier apex documentation + hygiene 2026-07-06 04:01:15 +02:00
TRUSTED-BASE.md Coherence pass 4 (the closing pass): 4-tier apex documentation + hygiene 2026-07-06 04:01:15 +02:00

dalek-ed25519-verified

Formal verification of the ed25519 implementation in dalek-cryptography/curve25519-dalek (upstream, v5.0.0-rc.1), built as a coherent proof pyramid in Lean 4 via the Charon/Aeneas transpilation pipeline:

        ┌──────────────────────────────┐
        │  Signature (EdDSA verify)    │   accepted ⇔ decompress(R) = [k](A)+[s]B
        ├──────────────────────────────┤
        │  Scalar arithmetic mod      │   Scalar52 ops correct mod 
        ├──────────────────────────────┤
        │  Group law (twisted Edwards) │   point ops = complete addition law
        ├──────────────────────────────┤
        │  Field 𝔽_p, p = 2²⁵⁵  19    │   FieldElement51 ops correct mod p
        └──────────────────────────────┘

Every layer states its theorems about the actual Aeneas-transpiled Rust code (never about a hand-written re-model), and every claim in the status table below is backed by a compiled proof plus an axiom audit of the named certificate. Files that do not compile under verification/check.sh are not in this repository.

Layer status

Layer Certificate Status Axioms of certificate
Field 𝔽_p fieldImplementation proven [propext, Classical.choice, Quot.sound]
Group law (Edwards) edwardsImplementation proven [propext, Classical.choice, Quot.sound]
Scalar mod scalarImplementation (add sub mul ) proven [propext, Classical.choice, Quot.sound]
Signature (EdDSA) verify_accepts_iffverify_accepts_iff_decompress (4 tiers) proven (phases 1+2) standard three + the button-enforced SHA-512/wire-format boundary — see The signature apex

Status legend: proven & axiom-audited · in progress · not started. This table is updated only when verification/check.sh passes for the layer.

The signature apex (phases 1 and 2)

The byte-level apex certificate CurveFieldProofs.verify_accepts_iff is the literal EdDSA acceptance criterion, proven about the extracted verifier:

For a signature that parses, the verifier returns Ok(()) iff the recomputed compressed point compress([s]·B [k]·A) equals the signature's R, byte-for-byte — where k is whatever scalar the opaque SHA-512 oracle produces from (R, A, msg).

The recomputation runs entirely through the proven model: the vendored ed25519-dalek verify glue is extracted as gen/CurveSig, whose hand-maintained externals import gen/CurveField — every curve and scalar call resolves by fully-qualified name to a proven definition. Only SHA-512 (three stateful wrapper calls) and the wire-format types stay opaque.

check.sh has a dedicated audit phase (Phase 3b) that fails the build unless the apex certificate's axiom cone is exactly

[propext, Classical.choice, Quot.sound] + {ed25519.Signature, sha2.Sha512, verifying.sha512_new, verifying.sha512_update, verifying.sha512_finalize_bytes, ed25519.Signature.to_bytes, signature.error.Error, signature.error.Error.new}

— i.e. the three Lean foundations plus the documented SHA-512/wire-format boundary. Zero curve, scalar, or backend axioms. The companion certificate verify_loop_full (the 32-byte comparison loop computes array equality) carries the standard three axioms only.

Phase 2 (complete): the point-level lift. Phase 3b enforces the SAME axiom boundary on three further tiers that lift the byte equation to points:

Tier Certificate Statement
half-lift verify_accepts_iff_point accepted ⇔ R = the canonical encoding of [k]·(A) + [s]·B (compress semantics + to_bytes canonicity + hash-to-scalar, recompute chain inverted)
point equation verify_accepts_iff_point_eq for any valid on-curve Q canonically encoded by R: accepted ⇔ Q = [k]·(A) + [s]·B as points (encoding-injectivity: d non-square + parity root-selection)
full lift verify_accepts_iff_decompress R decompresses to a valid on-curve Pt, and accepted ⇔ Pt = [k]·(A) + [s]·B — the constructive capstone

The full lift runs through the extracted CompressedEdwardsY::decompress itself, proven end-to-end: from_bytes parses the y-residue exactly below bit 255 (from_bytes_spec), sqrt_ratio_i returns the even square root of (y²1)/(dy²+1) (sqrt_ratio_i_sq_spec, Fermat-exponent square root), and the sign bit selects the x-parity (decompress_of_canonical, standard three axioms). Byte comparison ↔ encoding equality ↔ point equality ↔ decompressed-point equality: every link is machine-checked over the extracted code, and check.sh fails the build if any of the four tiers' cones deviates from the boundary above.

Source

  • Upstream: dalek-cryptography/curve25519-dalek, commit 4cf8db2
  • Pinned/patched source: saymrwulf/curve25519-dalek-source, commit aa0f6ab (adds the decompress step_2 negate-then-assign patch)
  • Patches: minimal Aeneas-compatibility only (documented in the source repo)
  • Verified backend: backend/serial/u64 (FieldElement51, Scalar52). SIMD/AVX backends are out of scope (marked opaque).

Toolchain (pinned)

Component Version
Aeneas bf13c42e
Charon 9dd7f23c
Lean v4.30.0-rc2
OCaml 5.3.0

Reproducing

source ~/aeneas-toolchain/env.sh
cd verification
./extract.sh    # Rust → LLBC → Lean (regenerates gen/)
./check.sh      # compiles EVERY shipped file + axiom-audits EVERY certificate

The gen model is ONE merged universe (gen/CurveField: field + curve + scalar + the verify path's reachable code), regenerated in full by extract.sh. The scalar layer keeps its own check button:

./check-scalar.sh     # compiles the merged gen + all scalar proofs (add, sub,
                      # Montgomery mul, byte-parsing) and kernel-audits the
                      # scalar certificates, incl. the scalarImplementation
                      # aggregate

Trusted base

See TRUSTED-BASE.md for the complete list of assumptions (Lean kernel, mathlib, Charon/Aeneas semantics, external-function models, and — in the signature layer only — an opaque SHA-512 model).