formal(refinement): prove verify_envelope fail-closed gates on the extracted Rust - #315
Open
hartsock wants to merge 1 commit into
Open
formal(refinement): prove verify_envelope fail-closed gates on the extracted Rust#315hartsock wants to merge 1 commit into
hartsock wants to merge 1 commit into
Conversation
…tracted Rust WHAT Three refinement theorems on the Charon/Aeneas-EXTRACTED, trait-generic `signed_object.verify_envelope`, discharging its fail-closed verification ORDER for ANY `SignedEnvelopeCodec` / `CryptoBoundary` instance: - Gate 1 `verify_envelope_undecodable_fails_closed`: an undecodable envelope (`decode = None`) rejects with `Undecodable` — nothing downstream is reached. - Gate 2 `verify_envelope_non_canonical_fails_closed`: a decodable envelope whose canonical re-encode does not byte-equal the received bytes rejects with `NonCanonicalEnvelope`, BEFORE any signature/cid check — the anti-malleability "verify against the received bytes, never a re-encode" law. - Gate 3 `verify_envelope_version_mismatch_fails_closed`: a canonical envelope whose declared profile version differs rejects with `VersionMismatch`. This one threads the reduction THROUGH a passing gate (the `ne = false` canonical branch), showing the technique follows the accept path, not only immediate short-circuits. Also: fill the `core.option.Option.ok_or` hole in FunsExternal.lean with its exact std semantics (`None ⇒ Err(e)`, `Some(x) ⇒ Ok(x)`) instead of the opaque axiom template. This lets `verify_envelope` reduce through the `Try`-operator chain AND removes an axiom from the extracted-code proof base. WHY The P1 signed-object obligations (#263) covered the algebra + admit/resolve/ store-id on the extracted code, but not the top-level `verify_envelope` gate itself. These theorems extend the Tier-3 bridge to the 6-step verifier's fail-closed order — the security-critical property the audit (§12) cares about — proven on the actual Rust as extracted, abstractly over the crypto/codec traits. Axiom footprint (checked via `#print axioms`): `[propext, Classical.choice, Quot.sound]` — mathlib's standard base, NO `sorryAx`, and no dependence on the former `ok_or` axiom. Remaining verify_envelope gates (hash/sig/codec admit, signature, cid, domain, unknown-critical, and the full accept path) follow the identical reduction pattern with more passing-gate hypotheses; deferred per freeze-minimally. Verified locally with `just check-refinement` (full `lake build` green, 1702 jobs). The Tier-3 refinement gate is deliberately not in the mandatory pre-push hook (it pulls the heavy Aeneas + mathlib backend). Co-Authored-By: Claude Opus 4.8 <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
Extends the Tier-3 (Charon/Aeneas) refinement to the top-level
verify_envelope— the 6-step signed-object verifier. The prior #263 obligations covered the authority algebra +admit/resolve/store_idon the extracted code, but not the verifier's own fail-closed order. These three theorems discharge it on the actual Rust as extracted, abstractly over ANYSignedEnvelopeCodec/CryptoBoundarytrait instance (Aeneas threads them as explicit dictionary args):verify_envelope_undecodable_fails_closed:decode = None⇒Err(Undecodable); nothing downstream (canonicalization, signature, cid) is reached.verify_envelope_non_canonical_fails_closed: a decodable envelope whose canonical re-encode does not byte-equal the received bytes ⇒Err(NonCanonicalEnvelope), before any version/algorithm/signature/cid check. This is the anti-malleability law — verify against the received bytes, never a re-encode — closing signature-stripping / re-serialization attacks.verify_envelope_version_mismatch_fails_closed: a canonical envelope with a mismatched profile version ⇒Err(VersionMismatch). Unlike 1–2, this reduction threads through a passing gate (thene = falsecanonical branch), demonstrating the technique follows the accept path, not only immediate short-circuits.ok_oraxiom → definitioncore.option.Option.ok_orwas an opaqueaxiominFunsExternal.lean(the "fill the holes" template), which stalled any reduction throughverify_envelope'sTry-operator chain. Filled it with its exact std semantics (None ⇒ Err(e),Some(x) ⇒ Ok(x)) — this unblocks the reduction and removes an axiom from the extracted-code proof base.Test plan
just check-refinementgreen locally:lake buildcompletes, 1702 jobs, no errors and nosorryin project declarations (the onlysorrywarnings are inside the Aeneas library's own axiomatized slice ops).#print axiomson all three theorems:[propext, Classical.choice, Quot.sound]— mathlib's standard base, nosorryAx, and no dependence on the formerok_oraxiom.formal/Ceremony gate + Rust suite (which this PR does not touch) passed on push.Out of scope
verify_envelopegates (hash/sig/codec admit, signature-invalid, cid-mismatch, body-domain, unknown-critical) and the full accept path (Ok(VerifiedEnvelope)). Each follows the identical reduction pattern with more passing-gate hypotheses; deferred per freeze-minimally.CryptoBoundarystays abstract).Note
Low Risk
Lean-only formal verification changes; no runtime Rust or crypto behavior is modified.
Overview
Extends Tier-3 Charon/Aeneas refinement to
verify_envelope, proving three early fail-closed gates on the extracted generic verifier (anySignedEnvelopeCodec/CryptoBoundaryinstances): undecodable →Undecodable, non-canonical bytes →NonCanonicalEnvelopebefore later checks, and version mismatch →VersionMismatchafter a passing canonical step.FunsExternal.leanreplaces the opaqueOption.ok_oraxiom with a definitional implementation (None/Some→Err/Ok) so proofs cansimpthrough the?/Trychain and drop one axiom from the proof base.Proofs live in
Refinement.leanassimp-only theorems parameterized by decode/encode/canonical hypotheses.Reviewed by Cursor Bugbot for commit d0aed1e. Configure here.