NomPkg Bridge: Game-Based Security → sdist #
This file bridges game-based security (∀ A, Advantage ≤ ε) to the categorical
sdist framework, enabling composition via post-processing lemmas.
Main results #
SPComp.NoFail— computation never produces failuresdist_le_of_advantage_bool— sdist for Bool-valued IsPure+NoFail SPComps from Advantagesdist_of_deepNomAdvantage— bridge for deep nominal packagesnomPkg_absorb— general absorption of post-processing into the adversary
Key insight #
For Bool-valued IsPure+NoFail computations, any post-processing distinguisher
D : Bool → SPComp Bool cannot increase the advantage beyond what the identity
distinguisher achieves. This is a post-processing lemma for binary channels.
NoFail #
A computation never fails: all mass is on successful outcomes.
Equations
- CatCrypt.Crypto.SPComp.NoFail c = ∀ (h : CatCrypt.Core.Heap), (c h) none = 0
Instances For
pure a never fails.
Compositional NoFail helpers #
Bind preserves NoFail: if c is NoFail and every f a is
NoFail, then c >>= f is NoFail.
SPComp.sample is NoFail: uniform distributions assign 0
mass to the failure slot.
IsPure + NoFail Helpers #
For IsPure c, the bind c >>= D at h₀ equals d.bind(fun a => D a h₀).
For IsPure+NoFail, the witness distribution d has d(none) = 0.
For IsPure c : SPComp Bool with witness d, the bind (d.bind f)(some(b, h₀))
is zero when h ≠ h₀, because d.bind produces outputs only at heap h₀.
For IsPure c : SPComp Bool, prTrue c h₀ = d(some true) for any h₀.
The heap doesn't affect the output distribution.
For IsPure+NoFail, d(some true) ≤ 1.
Algebraic Inequality: Convex Combination Bound #
Auxiliary: for r ≤ s ≤ 1, the expression with smaller weight r is bounded by the expression with larger weight s plus the weight difference (s - r). This is one direction of the convex bound.
Key algebraic fact: the absDiff of two convex combinations (with the same endpoints but different weights) is bounded by the absDiff of the weights.
This is the post-processing lemma for binary channels.
prTrue Decomposition for IsPure+NoFail Bool #
For IsPure+NoFail c : SPComp Bool, prTrue(c >>= D, h₀) decomposes as
p * prTrue(D true, h₀) + (1-p) * prTrue(D false, h₀) where p = d(some true).
D-Absorption for Bool (Post-Processing Lemma) #
Core D-absorption: for IsPure+NoFail c₁, c₂ : SPComp Bool, any D cannot increase the advantage beyond what the identity distinguisher achieves.
Main Bridge: Advantage → sdist #
Main bridge theorem: for Bool-valued IsPure+NoFail computations,
∀ a, Advantage(f a)(g a) ≤ ε implies sdist f g ≤ ε.
This combines:
sdist_isPure_le— absorbs h₀ into the distinguisher via IsPureabsDiff_bind_le_advantage— D-absorption for Bool with NoFail
NomPkg Bridge #
Bridge for deep nominal packages: game-based security implies sdist bound.
Given ∀ A : NomPkg, DeepNomAdvantage G G' A ≤ ε, this yields
sdist (fun A => runPkg(link A G)) (fun A => runPkg(link A G')) ≤ ε.
Requires IsPure+NoFail for the linked computations. Universe parameters are pinned to avoid auto-binding divergence.
General Absorption Bridge #
General absorption bridge: if for every (D, a, h₀) triple there exists
an a' whose Advantage dominates the post-processed advantage, then
sdist f g ≤ ε.
This cleanly separates:
- General math (this theorem): absorption implies sdist bound
- Protocol-specific claim (caller-provided): the adversary space can absorb post-processing D and initial heap h₀
NomPkg Absorption via Eval Completeness #
The key theorem: for any game pair (G, G'), post-processor D, adversary A, and initial heap h₀, there exists A' such that the post-processed absDiff is bounded by A's Advantage.
This uses RawCode.ofSPComp (from EvalComplete) to embed arbitrary SPComp
computations into the deep embedding, enabling construction of A' that wraps
A's oracle-calling code with heap reset and post-processing.
Reset heap to a target state. All existing heap contents are replaced.
Equations
Instances For
prTrue after heap reset shifts the initial heap.
Construct a NomPkg that wraps A's main export with heap reset and
post-processing D. A' has the same exports, imports, and locations as A,
but the (0, Unit, Bool) export is wrapped:
- Phase 1:
ofSPComp(heapReset h₀)— reset heap (no oracle calls) - Phase 2: A's original code (with oracle calls to game)
- Phase 3:
ofSPComp(D b)— post-process (no oracle calls)
Equations
- One or more equations did not get rendered due to their size.
Instances For
Key evaluation lemma: runPkg(wrapMain(A).link(G)) at Heap.empty
equals runPkg(A.link(G)).bind(D) at h₀.
After linking with G, oracle calls in A's code get resolved. The ofSPComp phases (heapReset and D) are transparent to substOracle.
General NomPkg absorption theorem.
For any game pair (G, G'), post-processor D, adversary A, and initial heap h₀, there exists A' whose Advantage dominates the post-processed absDiff. This is the core lemma for lifting game-based security to sdist.
The construction: A' wraps A's main export with heapReset h₀ (to shift
the initial heap) and D (to absorb post-processing). After linking with
G, the oracle calls in A's code get resolved as before, while the
ofSPComp phases are transparent to substOracle.
This eliminates the need for IsPure/NoFail assumptions.
Automation Tactic #
Tactic: bridge game-based advantage to sdist bound for NomPkg games.
Equations
- CatCrypt.Crypto.tacticSdist_from_deep = Lean.ParserDescr.node `CatCrypt.Crypto.tacticSdist_from_deep 1024 (Lean.ParserDescr.nonReservedSymbol "sdist_from_deep" false)
Instances For
Tactic: bridge a deep nominal advantage bound to a UCEmulates goal, via
UCEmulates_of_sdist then sdist_from_deep.
Equations
- CatCrypt.Crypto.tacticUc_from_deep = Lean.ParserDescr.node `CatCrypt.Crypto.tacticUc_from_deep 1024 (Lean.ParserDescr.nonReservedSymbol "uc_from_deep" false)