Documentation

CatCryptCore.Examples.Cryptobox.PKEY

PKEY: Public Key Management Game #

The PKEY game manages public key generation and corruption tracking.

Overview #

Two variants parameterized by b : Bool:

The PKEY Switching Lemma bounds the advantage by collision probability via FEL.

References #

Heap Locations #

State is stored in the global heap via typed locations. Locations are @[reducible] so that .ty reduces for type checking.

@[reducible]

Honesty flags: PK → Bool. Default: all false (unregistered).

Equations
Instances For
    @[reducible]

    Secret key storage: PK → SK. Only meaningful for honest keys.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      @[reducible]

      Corruption flags: PK → Bool. Default: all false.

      Equations
      Instances For

        Oracle Definitions #

        Each oracle is an SPComp computation that reads/writes heap locations. The b : Bool parameter in GEN switches collision behavior.

        GEN oracle: generate a fresh honest key pair. If b = true, asserts no collision with existing registered keys.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For

          CSETPK oracle: register an adversary-chosen public key as corrupt.

          Equations
          • One or more equations did not get rendered due to their size.
          Instances For

            GETSK oracle: retrieve the secret key for an honest public key.

            Equations
            • One or more equations did not get rendered due to their size.
            Instances For

              HONPK oracle: check whether a public key is one the challenger generated (rather than adversarially chosen).

              Equations
              Instances For

                Oracle Record #

                PKEY Game #

                PKEY game parameterized by collision behavior b.

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For

                  PKEY Collision Analysis #

                  The PKEY game switching argument is a failure event lemma (FEL) application. The key insight is that genOracle N false and genOracle N true differ only in the collision check: when honest pk || corrupt pk = false (no collision), both branches execute identically. When a collision DOES occur, the b=true version fails (produces 0 mass) while the b=false version continues.

                  Proof Structure #

                  To prove pkeyAdvantage N A ≤ ε via FEL, one needs:

                  1. Up-to-bad agreement: PKEY N false A and PKEY N true A agree on outcomes where no collision occurred during execution. This follows from the observation that genOracle N false and genOracle N true diverge only at the collision check, and all other oracles (csetpk, getsk, honpk) are identical.

                  2. Bad probability bound: The probability that a collision occurs during PKEY N false A is at most ε. With q_gen GEN queries and q_csetpk CSETPK queries, each GEN call samples a pk uniformly, and the collision probability is at most (#honest + #corrupt) / |PK| per call. By union bound: Pr[collision] ≤ q_gen * q_csetpk / |PK|.

                  Comparison with Other Formalizations #

                  Collision bad event for a single GEN call.

                  A collision occurs when the newly generated pk matches an existing honest or corrupt key. This is checked on the heap state BEFORE the honest flag is updated.

                  Equations
                  Instances For

                    Collision predicate on final heap.

                    The "bad event" for the FEL: there exists a pk that is registered as BOTH honest and corrupt. This is a necessary consequence of any collision during execution (since GEN sets honest and CSETPK sets corrupt, a collision means some pk ends up with both flags set).

                    Note: this is a necessary but not sufficient condition for a collision during execution. A stronger formulation would track the collision flag explicitly (requiring an instrumented game).

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For

                      PKEY collision-checking oracle record. Convenience for building oracle records.

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For

                        PKEY non-collision-checking oracle record.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For

                          PKEY game with explicit oracle record is definitionally equal to PKEY.

                          genOracle Analysis #

                          Properties of the collision check in genOracle. These are building blocks for proving the up-to-bad agreement condition.

                          theorem CatCrypt.Examples.Cryptobox.genOracle_unfold [CT : CryptoTypes] (N : NIKEScheme) (b : Bool) :
                          genOracle N b = do let pair ← N.pkgen have pk : CryptoTypes.PK := pair.1 have sk : CryptoTypes.SK := pair.2 let honest ← Core.SPComp.get pkHonestLoc let corrupt ← Core.SPComp.get pkCorruptLoc have __do_jp : Unit → Core.SPComp CryptoTypes.PK := fun (__r : Unit) => do let skMap ← Core.SPComp.get skStoreLoc Core.SPComp.set pkHonestLoc (Function.update honest pk true) Core.SPComp.set skStoreLoc (Function.update skMap pk sk) Core.SPComp.pure pk if b = true then if (honest pk || corrupt pk) = true then do let __r ← Core.SPComp.fail __do_jp __r else do let __r ← Core.SPComp.pure () __do_jp __r else do let __r ← Core.SPComp.pure () __do_jp __r

                          genOracle N false and genOracle N true differ only in the collision check.

                          When b = false: the collision check is skipped (SPComp.pure ()) When b = true: the collision check may fail (if coll then fail else pure ())

                          The rest of the oracle body (sample, read honest/corrupt/skMap, update, return pk) is identical in both cases.

                          PKEY FEL Application #

                          Application of the Failure Event Lemma to bound the PKEY advantage. The bad event is pkeyBadFinal: some public key is both honest and corrupt in the final heap.

                          PKEY advantage bounded by collision probability via FEL.

                          This instantiates advantage_le_prBad from FailureEvent.lean with the PKEY-specific bad event (pkeyBadFinal).

                          The two hypotheses that must be discharged for a specific adversary B:

                          1. Up-to-bad agreement (h_agree): When no collision occurs (no pk is both honest and corrupt in the final heap), the two PKEY games produce the same distribution. This follows from the fact that genOracle N false and genOracle N true differ only in the collision check, which is vacuous when no collision occurs.

                            For a concrete adversary, this requires showing that the adversary's oracle calls compose correctly — see agree_bind_left and agree_bind_both from FailureEvent.lean for the composition lemmas.

                          2. Losslessness (hll): The PKEY N false B game is lossless (total mass 1). This requires showing that genOracle N false never fails (it skips the collision check) and that the adversary B doesn't cause failure on its own.

                          theorem CatCrypt.Examples.Cryptobox.pkey_switching [CT : CryptoTypes] (N : NIKEScheme) (B : PKEYOracles → Core.SPComp Bool) (coll_bound : ENNReal) (h_agree : ∀ (b : Bool) (h' : Core.Heap), ¬pkeyBadFinal h' → (PKEY N false B Core.Heap.empty) (some (b, h')) = (PKEY N true B Core.Heap.empty) (some (b, h'))) (hll : Unary.isLossless (PKEY N false B)) (hcoll : (Unary.prEventComp (PKEY N false B) Core.Heap.empty fun (x : Bool) (h' : Core.Heap) => pkeyBadFinal h') ≤ coll_bound) :
                          pkeyAdvantage N B ≤ coll_bound

                          PKEY switching as a game hop: when the two PKEY games agree off the collision event pkeyBadFinal, the collision-free game is lossless, and the probability of pkeyBadFinal in the collision-free game is at most coll_bound, the switching advantage is at most coll_bound. The bound on the collision probability is a hypothesis on the collision-free game; collision_prob_single_query bounds the collision probability of one GEN query and collision_prob_multi_query_bound evaluates the union-bound sum over the queries.

                          Collision-Flag Instrumented Game Infrastructure #

                          The pkeyBadFinal bad event (∃ pk, honest[pk] ∧ corrupt[pk]) is insufficient for a precise FEL argument because genOracle N true also fails on duplicate honest keys, not just honest-corrupt cross collisions.

                          We introduce an instrumented variant of the PKEY game that explicitly sets a collision flag whenever the generated pk collides with ANY existing key (honest or corrupt). This gives a stronger, more precise bad event for FEL.

                          @[reducible]

                          Collision flag location. Set to true when a GEN call produces a pk that collides with an existing honest or corrupt key.

                          Equations
                          Instances For

                            Instrumented GEN oracle: like genOracle but sets pkeyCollFlag on collision.

                            When a collision is detected (the newly generated pk is already honest or corrupt):

                            • Always sets the collision flag to true
                            • If b = true: fails (collision-checking mode)
                            • If b = false: continues without failing (non-collision-checking mode)

                            When no collision is detected: both b = true and b = false execute identically.

                            Equations
                            • One or more equations did not get rendered due to their size.
                            Instances For

                              Instrumented bad event: the collision flag is set.

                              This is a precise characterization of "some GEN call produced a collision during execution", unlike pkeyBadFinal which only captures the weaker condition of a pk being both honest and corrupt simultaneously.

                              Equations
                              Instances For

                                Instrumented PKEY game: uses genOracle_instr instead of genOracle.

                                All other oracles (CSETPK, GETSK, HONPK) are unchanged.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For

                                  Instrumented oracle records for convenience.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For
                                      theorem CatCrypt.Examples.Cryptobox.genOracle_instr_unfold [CT : CryptoTypes] (N : NIKEScheme) (b : Bool) :
                                      genOracle_instr N b = do let pair ← N.pkgen have pk : CryptoTypes.PK := pair.1 have sk : CryptoTypes.SK := pair.2 let honest ← Core.SPComp.get pkHonestLoc let corrupt ← Core.SPComp.get pkCorruptLoc have __do_jp : Unit → Core.SPComp CryptoTypes.PK := fun (__r : Unit) => do let skMap ← Core.SPComp.get skStoreLoc Core.SPComp.set pkHonestLoc (Function.update honest pk true) Core.SPComp.set skStoreLoc (Function.update skMap pk sk) Core.SPComp.pure pk if (honest pk || corrupt pk) = true then do Core.SPComp.set pkeyCollFlag true if b = true then do let __r ← Core.SPComp.fail __do_jp __r else do let __r ← Core.SPComp.pure () __do_jp __r else do let __r ← Core.SPComp.pure () __do_jp __r

                                      Unfolding lemma for genOracle_instr.

                                      Key Theorem: Instrumented Oracles Agree When No Collision #

                                      When the collision flag is NOT set in the final heap, the collision branch was never taken during execution. Therefore, genOracle_instr N false and genOracle_instr N true produce identical distributions on non-bad outcomes.

                                      For any outcome (pk, h') with ¬pkeyBadInstr h' (i.e., Heap.get h' pkeyCollFlag ≠ true):

                                      1. Both genOracle_instr N false and genOracle_instr N true begin identically: sample pair ← N.pkgen, read honest, corrupt.

                                      2. At the distribution level, the result at outcome (pk, h') is a sum over intermediate states:

                                        (genOracle_instr N b h₀)(some (pk, h')) =
                                          ∑_{pair, h₁} (N.pkgen h₀)(some (pair, h₁)) *
                                            (rest_b pair.1 pair.2 h₁)(some (pk, h'))
                                        
                                      3. For each intermediate (pair, h₁), let pk_gen = pair.1. Read honest = Heap.get h₁ pkHonestLoc and corrupt = Heap.get h₁ pkCorruptLoc.

                                      4. Case: honest pk_gen || corrupt pk_gen = true (collision detected):

                                        • Both variants set pkeyCollFlag := true in the heap.
                                        • The b = true variant then calls SPComp.fail, producing 0 mass.
                                        • The b = false variant continues and produces h' with pkeyCollFlag = true.
                                        • But we assumed ¬pkeyBadInstr h', i.e., Heap.get h' pkeyCollFlag ≠ true.
                                        • The collision flag, once set to true, persists through subsequent set calls on OTHER locations (pkHonestLoc, skStoreLoc have different ids: 100, 101 vs 103).
                                        • So Heap.get h' pkeyCollFlag = true, contradicting ¬pkeyBadInstr h'.
                                        • Conclusion: this intermediate contributes 0 mass for BOTH b = false and b = true.
                                      5. Case: honest pk_gen || corrupt pk_gen = false (no collision):

                                        • Both variants execute SPComp.pure (), then identically update the heap.
                                        • The rest of the computation is b-independent.
                                        • Conclusion: identical contribution for both b = false and b = true.
                                      6. Therefore, every term in the sum is equal, so the total is equal.

                                      theorem CatCrypt.Examples.Cryptobox.spcomp_bind_congr_left {α β : Type} {c₁ c₂ : Core.SPComp α} (f : α → Core.SPComp β) (h : c₁ = c₂) :
                                      c₁.bind f = c₂.bind f

                                      PKEY instrumented advantage bounded by collision probability via FEL.

                                      This is the instrumented analogue of pkeyAdvantage_le_collision. The stronger bad event pkeyBadInstr (collision flag set) gives a tighter and more precise bound than pkeyBadFinal (honest-corrupt overlap).

                                      The instrumented bad event implies the original bad event when there exists a key that is both honest and corrupt.

                                      More precisely: if a collision flag was set during a GEN call where honest pk_gen || corrupt pk_gen = true, then either:

                                      • The pk was already honest, and GEN sets it honest again (duplicate honest key)
                                      • The pk was already corrupt, and GEN sets it honest (honest-corrupt overlap → pkeyBadFinal)

                                      Note: pkeyBadInstr is STRICTLY stronger than pkeyBadFinal because it also catches duplicate honest-honest collisions.

                                      Per-Query Collision Probability #

                                      For a single GEN query, the probability that the newly sampled pk collides with existing keys depends on the number of already-registered keys and the size of the pk space.

                                      Per-query collision probability bound.

                                      The collision set on heap h₀ is the set of pk whose pkHonestLoc or pkCorruptLoc flag is set. If it is covered by a finset S of size q_existing, then a public key sampled uniformly from CT.PK lands in the collision set with probability at most q_existing / Fintype.card CT.PK. This is the per-GEN-query collision probability under uniform key generation.

                                      theorem CatCrypt.Examples.Cryptobox.collision_prob_multi_query_bound [CT : CryptoTypes] (q_gen q_csetpk : ℕ) :
                                      ∑ i ∈ Finset.range q_gen, (↑i + ↑q_csetpk) / ↑(Fintype.card CryptoTypes.PK) = ↑(q_gen * (q_gen - 1) + 2 * (q_gen * q_csetpk)) / (2 * ↑(Fintype.card CryptoTypes.PK))

                                      Multi-query collision bound via union bound.

                                      With q_gen GEN queries, the i-th of which (0-indexed) has at most i existing challenger-generated keys plus q_csetpk corrupt keys, the union bound over the per-query collision probabilities is the sum ∑_{i=0}^{q_gen-1} (i + q_csetpk) / |PK|. This sum equals the birthday closed form (q_gen * (q_gen - 1) + 2 * (q_gen * q_csetpk)) / (2 * |PK|).

                                      Standalone PKEY sdist Building Block #

                                      Standalone PKEY sdist building block. Reusable by any construction that uses the PKEY game.

                                      Bridges per-adversary advantage bounds (∀ A, pkeyAdvantage N A ≤ ε) to categorical sdist (sdist (PKEY N false) (PKEY N true) ≤ ε), giving access to PPLs, composition, and tensor bounds.