OneWayness GameHop: Up-to-Bad Hop (Game 1 → Game 2), relationally #
This module bounds the difference between ow_game_1_tracked and
ow_game_2_tracked by the bad event (the adversary queried chal_x).
The two games differ only in whether the random oracle is pre-programmed
at chal_x (Game 1 does, Game 2 doesn't).
One pRHL judgment delivers everything (ow_game_tracked_relE):
G1 ~ G2 : Eq ⇒ PostG where PostG says the bad flags agree and, on good
runs, the results agree and the states differ only by the pre-programmed
RO entry. The coupling invariant carried through the adversary loop is
InvUB x y σ₁ σ₂ := flag σ₁ = flag σ₂
∧ (flag σ₁ = false → chal_x σ₂ = x ∧ σ₁ = insRO x y σ₂)
The per-query coupling lqt_relE is proved by exhibiting one coupling per
cache branch (relE.of_coupling); the after-bad phase is the rectangular
rule rel.of_unary, whose side conditions are the flag-monotonicity and
mass-1 facts.
Main results (all corollaries of the judgment) #
ow_game_1_tracked_eq_ow_game_2_tracked_until_bad— agree-until-bad (viarelE.wp_eq).ow_game_1_tracked_bad_eq_ow_game_2_tracked_bad— bad events agree (viarelE.bad_eq; the former unary proof needed a 138-line mass-conservation/cancellation chain).ow_game_1_tracked_le_ow_game_2_tracked_plus_bad— the hop bound (viarelE.up_to_bad).
Hypothesis note: the single-judgment route needs the adversary's mass-1 hypothesis for all three results (the rectangular phase needs the right side to be lossless). The OW master theorem assumes it anyway.
The former ~790-line unary development (per-step RO-invariance machinery, flag-true-zero family, mass block, hand-rolled identical-until-bad induction) was replaced by this relational proof; see git history.
Tracking is invisible to flag-ignoring posts (kept: used by Game1) #
One lazy_query_tracked is wp-equivalent to one lazy_query for any
flag-ignoring continuation whose post is also flag-ignoring.
The RO[chal_x] insertion point #
insert_at_chal_x is the state-indexed form of the pre-programming write
(position read from the state); the relational development below uses the
fixed-position form insRO and relates the two where needed.
Shorthand: the state with RO[chal_x] forcibly set to some y_chal.
Equations
- insert_at_chal_x y_chal σ = random_oracle_state.set (fun (k : input) => if k = ow_challenge_x.get σ then some y_chal else random_oracle_state.get σ k) σ
Instances For
The shift function and the coupling invariant #
Overwrite the RO entry at the (fixed) position x with some y.
This is insert_at_chal_x with the position decoupled from the state.
Equations
Instances For
Reading any RO-disjoint lens through insRO is invisible.
The coupling invariant between the Game-1 run (left) and the
Game-2 run (right): flags agree; on good runs the left state is the
right state with RO[x ↦ y] overwritten and the right challenge is x.
Equations
- InvUB x y σ₁ σ₂ = (chal_x_queried_gh.get σ₁ = chal_x_queried_gh.get σ₂ ∧ (chal_x_queried_gh.get σ₁ = false → ow_challenge_x.get σ₂ = x ∧ σ₁ = insRO x y σ₂))
Instances For
Closed wp forms (the wp-tactic analogue) #
Decompose lazy_query_tracked.wp into a lazy_query.wp with the
flag-branching folded into the post.
The per-query coupling (the heart of the hop) #
lazy_query_tracked inp relates to itself across insRO x y:
inp ≠ x: both sides read the same cache entry — hit-hit returns the same value, miss-miss couples the fresh sample identically and the new entry commutes with thex-overwrite. Good post, equal values.inp = x: the left side hits the pre-programmed entry while the right side does whatever its cache says — but both set the flag. Bad post.
Proved by exhibiting one coupling per branch (relE.of_coupling), so both
judgment directions come from a single case analysis.
Bad-phase unary side conditions (flag monotonicity and mass) #
Indicator complement trick: full mass + zero on the complement gives mass 1 on the event.
The verification segment shared by both games (parameterized by the
challenge output y_v it compares against).
Equations
- finalSeg y_v = do let resp ← GaudisCrypt.ProgramDenotation.get ow_response let y_check ← lazy_query_tracked resp pure (decide (y_check = y_v))
Instances For
The rectangular (after-bad) judgments #
The good-phase judgments #
The full loop-body judgment: Inv is preserved by one oracle step.
The game-level judgment #
The game-level judgment: tracked Game 1 and tracked Game 2 are related at "flags agree, and on good runs the results agree and the states differ only by the pre-programmed RO entry". All three up-to-bad theorems are corollaries.
The three theorems of the unary development, as corollaries #
Bad-event probability equality (the unary original needed a 138-line mass-conservation + ENNReal-cancellation chain).
The up-to-bad hop bound:
Pr[G1 : G] ≤ Pr[G2 : G] + Pr[G1 : bad ∧ G].