Nominal Advantage #
This file defines advantage for nominal packages via the deep embedding.
DeepNomAdvantage uses DeepPackage.link for actual oracle substitution
via RawCode.substOracle, enabling adversary-game composition.
Main definitions #
runPkg- Evaluate aDeepPackage's main export(0, Unit, Bool)DeepNomAdvantage- Distinguishing probability with adversary compositionNomPkgSecure- Adversary-dependent game-based security
References #
Running deep packages #
Run a deep package by evaluating its "main" exported operation.
Convention: the main entry point is export operation (0, Unit, Bool).
This mirrors the cryptographic game convention where the adversary's
main procedure takes no input and returns a boolean guess.
If the package exports (0, Unit, Bool), we evaluate the corresponding
RawCode Bool via RawCode.eval to get an SPComp Bool.
Otherwise, the package has no main entry point and we return pure true.
In the adversary-composition model:
- The adversary
Aexports(0, Unit, Bool)(itsmainprocedure) - The adversary imports operations from the game
G DeepPackage.link A.pkg G.pkgresolves A's oracle calls via G's exportsrunPkgevaluates the linked adversary's main procedure
Equations
Instances For
Run a deep nominal package by delegating to runPkg on the underlying
DeepPackage. The nominal structure (registry, atoms) is used only for
separation reasoning, not for evaluation.
Equations
Instances For
Advantage on deep nominal packages with adversary composition.
DeepNomAdvantage G G' A measures how well adversary A can distinguish
game G from game G':
DeepNomAdvantage G G' A = |Pr[eval(A ∥ G) => 1] - Pr[eval(A ∥ G') => 1]|
The adversary A is linked with each game via DeepPackage.link:
A.pkgexports the main procedure(0, Unit, Bool)A.pkgimports operations thatG.pkg/G'.pkgexport- Linking resolves A's oracle calls with G's (resp. G's) implementations
runPkgevaluates the linked package's main procedure
The atom separation between A and G/G' is an implicit precondition for meaningful security statements.
Equations
- CatCrypt.Crypto.DeepNomAdvantage G G' A = CatCrypt.Crypto.Advantage (CatCrypt.Crypto.runPkg (A.pkg.link G.pkg)) (CatCrypt.Crypto.runPkg (A.pkg.link G'.pkg))
Instances For
Triangle inequality for deep nominal advantage.
Self-advantage is zero for deep nominal packages.
Deep nominal advantage is symmetric.
Advantage equality under runPkg equivalence.
If two game pairs produce the same SPComp Bool when linked with adversary A,
then they have the same advantage. This is the key lemma for code equivalence
proofs: show that runPkg (link A G₀) = runPkg (link A G₀') (and similarly
for G₁/G₁'), then conclude the advantages are equal.
Typical use: after showing that G₀ and G₀' have the same oracle implementations
via runPkg_link_congr, apply this lemma to rewrite the advantage.
Advantage equality when games are NomPackage-equal.
A corollary of DeepNomAdvantage_runPkg_eq for the common case where
the games are literally equal as NomPackage values.
Linking Correctness #
The foundational theorem connecting DeepPackage.link with RawCode.eval:
running a linked package is the same as running the first package's main
procedure with oracle calls resolved through the second package.
Correctness of package linking with respect to evaluation.
Running a linked package runPkg (link p₁ p₂) is equivalent to
evaluating p₁'s main procedure (0, Unit, Bool) with an oracle handler
that resolves oracle calls through p₂:
- If
(op, dom, codom)is in p₂'s exports, the oracle call is replaced by evaluating p₂'s implementation. - Otherwise, the oracle call evaluates to
SPComp.fail.
This theorem is the semantic justification for DeepNomAdvantage:
it shows that DeepPackage.link (a syntactic operation on the free monad)
correctly implements oracle resolution at the semantic level (SPComp).
Proof: Unfolds runPkg and DeepPackage.link, then applies
eval_substOracle which proves the commutativity of substOracle
with eval by structural induction on RawCode.
Corollary: If two games have the same oracle implementations for all operations that the adversary calls, then the linked packages produce the same computation.
This is the key lemma for proving DeepNomAdvantage G G' A = 0
when G and G' agree on the operations that A imports.
Link Associativity #
Definitional equality link (link p₁ p₂) p₃ = link p₁ (link p₂ p₃) does NOT
hold because the oracle substitution environments have different structure.
However, both sides produce the same SPComp Bool when evaluated via runPkg.
The key insight: in both formulations, oracle calls in p₁ are resolved as follows:
- If the operation is in p₂'s exports: use p₂'s implementation, with p₂'s own oracle calls resolved through p₃
- If the operation is NOT in p₂'s exports: evaluate to
fail(Left:fail.substOracle env₃ = fail; Right:link p₂ p₃only exportsp₂.exports, so the lookup fails)
Therefore the two sides agree semantically.
Link associativity at the evaluation level.
runPkg (link (link p₁ p₂) p₃) = runPkg (link p₁ (link p₂ p₃))
This is the correct formulation of link associativity. We cannot prove
link (link p₁ p₂) p₃ = link p₁ (link p₂ p₃) as a definitional equality
on DeepPackage because the oracle substitution environments differ structurally.
But at the semantic level (after evaluation to SPComp via runPkg), they agree.
The proof uses:
eval_substOracle: substOracle commutes with evalevalWith_substOracle: composed evalWith decomposessubstOracle_comp: double substitution equals composed substitution
This theorem is critical for the reduction lemma DeepNomAdvantage_link.
Advantage Link (Reduction Lemma) #
The key theorem for security reductions: composing a reduction R with both games is equivalent to having R as part of the adversary.
DeepNomAdvantage G₀ G₁ ⟨link A R⟩ = DeepNomAdvantage ⟨link R G₀⟩ ⟨link R G₁⟩ A
This follows from link associativity: link (link A R) G = link A (link R G) So: runPkg (link (link A R) G₀) = runPkg (link A (link R G₀)) runPkg (link (link A R) G₁) = runPkg (link A (link R G₁))
Advantage link (reduction lemma) using NomPackage.link.
Composing a reduction wrapper R with both games is equivalent to
having R as part of the adversary:
DeepNomAdvantage G₀ G₁ (link A R) = DeepNomAdvantage (link R G₀) (link R G₁) A
This follows directly from runPkg_link_assoc:
link (link A.pkg R.pkg) G₀.pkgevaluates the same aslink A.pkg (link R.pkg G₀.pkg)link (link A.pkg R.pkg) G₁.pkgevaluates the same aslink A.pkg (link R.pkg G₁.pkg)
This theorem is critical for modular security proofs: it allows us to "absorb" a reduction wrapper R into the adversary A, which is the standard technique for composing security games in hybrid arguments.
Requires compatible registries (all packages use the same registry).
ID Package Properties #
Linking with the identity package on the right preserves evaluation.
runPkg (link p (id p.imports)) = runPkg p
This holds because:
idforwards all oracle calls, sooracleCall->oracleCall- For p's code, after substOracle with id's env, oracle calls that are in p.imports remain as oracle calls (id forwards them)
- Oracle calls not in p.imports become fail (same as unlinked evaluation)
- In both cases,
evalmaps unresolved oracle calls toSPComp.fail
So the link with id is semantically a no-op.
Linking with the identity package on the left preserves evaluation,
provided the main entry point (0, Unit, Bool) is in p's exports.
runPkg (link (id p.exports) p) = runPkg p
This holds because id p.exports's implementation is just oracleCall,
which after linking with p gets substituted with p's actual implementation.
Interchange Law #
The fundamental interchange law for packages:
link (par p₁ p₂) (par p₃ p₄) ≈ par (link p₁ p₃) (link p₂ p₄)
at the evaluation level (runPkg equality).
This requires an interface matching condition: the oracle environment from
par p₃ p₄ must agree with p₃'s environment for operations that p₁ calls
(and symmetrically with p₄ for operations that p₂ calls).
In a fully typed setting (where package types encode P : package M E),
this condition holds by construction: p₁ only calls operations in M,
which are exactly p₃'s exports.
Interchange law for package composition.
At the evaluation level:
runPkg (link (par p₁ p₂ h₁₂) (par p₃ p₄ h₃₄))
= runPkg (par (link p₁ p₃) (link p₂ p₄) h_link)
The interface matching condition h_env requires that the oracle
environment from par p₃ p₄ agrees with p₃'s environment at the
eval level. This is automatically satisfied when:
- p₃ and p₄ have disjoint export operation ids, AND
- p₁ only makes oracle calls to operations in p₃.exports
The proof reduces both sides to evalWith form on the same code,
then uses evalWith_congr with the environment agreement hypothesis.
Advantage under Parallel Composition #
The interchange law enables reasoning about advantage under parallel composition: the common component C can be absorbed into the adversary.
NomPackage.par / NomPackage.link now exist (Deep/Package.lean), and the
runPkg-level interchange law is runPkg_interchange above. The remaining
ingredient for DeepNomAdvantage_par is a runPkg-projection lemma
(runPkg (par X Y) = runPkg Y when the main export (0, Unit, Bool) ∈ Y),
after which the common-component-absorption statement
DeepNomAdvantage (par C G₀) (par C G₁) (par A_C A_G) = DeepNomAdvantage G₀ G₁ A_G
follows by rewriting each linked run through runPkg_interchange (adversary
par A_C A_G, game par C G) and projecting onto the varying link A_G G
component.
runPkg projection onto the right component of a parallel composition.
When the main export (0, Unit, Bool) is provided by the right package
Y (and NOT by the left package X), running the parallel composition
par X Y dispatches the main entry to Y, so it evaluates exactly as
runPkg Y.
The par implementation dispatches (0, Unit, Bool) to Y because it is
absent from X.exports (h_notX); par_impl_code_eq_right then equates
the dispatched code with Y's implementation code (the mono extension
to the union of locations is code-preserving).
Interchange law (right-dispatch variant).
The mirror of runPkg_interchange for the case where the main entry
(0, Unit, Bool) is exported by the right adversary component p₂
(and not by p₁). Running link (par p₁ p₂) (par p₃ p₄) then dispatches
the main entry through p₂, whose oracle calls resolve against p₄, so
it equals running par (link p₁ p₃) (link p₂ p₄).
The interface-matching hypothesis h_env requires the oracle environment
of par p₃ p₄ to agree (at eval level) with p₄'s environment — the game
component that the main-bearing adversary p₂ actually calls.
Advantage under parallel composition: common-component absorption.
A common component C shared by both games can be absorbed into the
adversary: distinguishing par C G₀ from par C G₁ with the composed
adversary par A_C A_G is exactly as hard as distinguishing G₀ from
G₁ with A_G, where A_G is the main-bearing adversary component and
A_C is the wrapper connecting to C.
DeepNomAdvantage (par C G₀) (par C G₁) (par A_C A_G) = DeepNomAdvantage G₀ G₁ A_G
Each linked run is rewritten through runPkg_interchange_right (adversary
par A_C A_G, game par C Gᵢ, main entry in the right component A_G)
into par (link A_C C) (link A_G Gᵢ), then projected with
runPkg_par_right onto the varying link A_G Gᵢ component.
The two h_env hypotheses are the interchange interface-matching
conditions: the oracle environment of par C Gᵢ must agree at eval level
with Gᵢ's environment — the game part that A_G actually calls. The two
h_link_sep hypotheses record location-separation of the absorbed runs.
NomPkgSecure: Game-Based UC for Deep Packages #
NomPkgSecure G G' ε says that for all adversaries A, the advantage of
distinguishing G from G' (via deep linking) is bounded by ε A.
This is the analogue of GameUCEmulates (UC.lean) for the deep package model
where adversaries are NomPackage rather than oracle-to-SPComp functions.
The bound is adversary-dependent: ε : NomPackage → ℝ≥0∞. This is essential
for concrete security (time/query complexity bounds). For composition, the
adversary-dependent bounds add pointwise.
Relationship to other security notions #
| Notion | Adversary | Composable | Axioms |
|---|---|---|---|
NomPkgSecure | NomPkg | via triangle | 0 |
GameUCEmulates | OracleIf → SPComp Bool | via triangle | 0 |
| sdist ≤ ε | (absorbed) | full PPL | 0 |
UCEmulates | (∀A ∃S) | full UC | 0 |
For TLS games (which use heap state), NomPkgSecure is the strongest notion
achievable without proving IsPure for linked packages.
Adversary-dependent game-based security for NomPkg games.
NomPkgSecure G G' ε states that for all adversaries A : NomPackage,
the advantage of distinguishing G from G' is bounded by ε A.
This captures the standard cryptographic game-based security notion where the bound depends on the adversary's complexity (time, oracle queries).
Equations
- CatCrypt.Crypto.NomPkgSecure G G' ε = ∀ (A : CatCrypt.Deep.NomPackage), CatCrypt.Crypto.DeepNomAdvantage G G' A ≤ ε A
Instances For
Reflexivity: any game is trivially secure against itself.
Symmetry: swapping real and ideal preserves the bound.
Transitivity: composition via triangle inequality. The adversary-dependent bounds add pointwise.
Monotonicity: weakening the bound.
Uniform bound version: when the bound doesn't depend on the adversary.