Skip to content

Commit 7fce4e4

Browse files
committed
refactor(CKA): match ACD19 Fig. 3 counter convention
Every oracle (send, recv, chall) now increments tP at the start, before protocol logic. Recv oracles also advance the counter. This matches [ACD19, Fig. 3] exactly, so finishedP uses non-strict ≤ with ΔCKA = 1 and corruption is safe: recv overwrites the challenge scalar before finishedP becomes true. Changes: - Defs.lean: restructure all oracles to increment-at-start; recv oracles now advance tA/tB; chall oracles check post-increment tP == tStar. - Security.lean: same convention in all reduction and hybrid oracles; hybridProj windows adjusted (tA == tStar, tB == tStar - 1); diagrams and docstrings updated. Made-with: Cursor
1 parent d21ef3c commit 7fce4e4

2 files changed

Lines changed: 129 additions & 145 deletions

File tree

Examples/CKA/Defs.lean

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -169,163 +169,154 @@ def ckaSecuritySpec (St Rho I : Type) :=
169169

170170
/-! ### Send oracles -/
171171

172-
/-- **O-Send-A.** `(key, ρ, stA') ← sendA(stA)`; return `(ρ, key)` to adversary;
173-
advance epoch `tA ← tA + 1`. -/
172+
/-- **O-Send-A.** `tA++; (key, ρ, stA') ← sendA(stA)`; return `(ρ, key)`.
173+
Following [ACD19, Fig. 3], the counter is advanced before protocol logic. -/
174174
def oracleSendA (cka : CKAScheme ProbComp IK St I Rho) :
175175
QueryImpl (Unit →ₒ Option (Rho × I)) (StateT (GameState St I Rho) ProbComp) :=
176176
fun () => do
177177
let state ← get
178-
-- Guard: alternating ok
179178
if validStep state.lastAction .sendA then
180-
-- (key, ρ, stA') ← sendA(stA)
179+
-- tA++ (before protocol logic, matching paper)
180+
let state := { state with tA := state.tA + 1 }
181181
match ← liftM (cka.sendA state.stA) with
182182
| none => pure none
183183
| some (key, ρ, stA') =>
184-
-- stA ← stA', tA ← tA + 1
185184
set { state with
186185
stA := stA', lastRhoA := some ρ, lastKeyA := some key,
187-
lastAction := some .sendA, tA := state.tA + 1 }
188-
-- return (ρ, key) to adversary
186+
lastAction := some .sendA }
189187
return some (ρ, key)
190188
else pure none
191189

192-
/-- **O-Send-B.** `(key, ρ, stB') ← sendB(stB)`; return `(ρ, key)` to adversary;
193-
advance epoch `tB ← tB + 1`. -/
190+
/-- **O-Send-B.** `tB++; (key, ρ, stB') ← sendB(stB)`; return `(ρ, key)`.
191+
Following [ACD19, Fig. 3], the counter is advanced before protocol logic. -/
194192
def oracleSendB (cka : CKAScheme ProbComp IK St I Rho) :
195193
QueryImpl (Unit →ₒ Option (Rho × I)) (StateT (GameState St I Rho) ProbComp) :=
196194
fun () => do
197195
let state ← get
198-
-- Guard: alternating ok
199196
if validStep state.lastAction .sendB then
200-
-- (key, ρ, stB') ← sendB(stB)
197+
-- tB++ (before protocol logic, matching paper)
198+
let state := { state with tB := state.tB + 1 }
201199
match ← liftM (cka.sendB state.stB) with
202200
| none => pure none
203201
| some (key, ρ, stB') =>
204-
-- stB ← stB', tB ← tB + 1
205202
set { state with
206203
stB := stB', lastRhoB := some ρ, lastKeyB := some key,
207-
lastAction := some .sendB, tB := state.tB + 1 }
208-
-- return (ρ, key) to adversary
204+
lastAction := some .sendB }
209205
return some (ρ, key)
210206
else pure none
211207

212208
/-! ### Receive oracles -/
213209

214-
/-- **O-Recv-A.** Deliver pending message `ρ` from B to A:
215-
`(keyA, stA') ← recvA(stA, ρ)`; assert `keyA = lastKeyB`
216-
(updating `correct`); clear pending `(lastRhoB, lastKeyB)`. -/
210+
/-- **O-Recv-A.** `tA++; (keyA, stA') ← recvA(stA, ρ)`; assert `keyA = lastKeyB`.
211+
Following [ACD19, Fig. 3], recv also advances the counter. -/
217212
def oracleRecvA [DecidableEq I] (cka : CKAScheme ProbComp IK St I Rho) :
218213
QueryImpl (Unit →ₒ Unit) (StateT (GameState St I Rho) ProbComp) :=
219214
fun () => do
220215
let state ← get
221-
-- Guard: alternating ok
222216
if validStep state.lastAction .recvA then
223-
-- ρ := lastRhoB (pending B → A message)
217+
-- tA++ (before protocol logic, matching paper)
218+
let state := { state with tA := state.tA + 1 }
224219
match state.lastRhoB with
225220
| none => pure ()
226221
| some ρ =>
227-
-- (keyA, stA') ← recvA(stA, ρ)
228222
match cka.recvA state.stA ρ with
229223
| none => pure ()
230224
| some (keyA, stA') =>
231-
-- ok := (keyA = lastKeyB)
232225
let ok := match state.lastKeyB with
233226
| some keyB => decide (some keyA = some keyB)
234227
| none => false
235-
-- stA ← stA', correct ← correct ∧ ok, clear pending
236228
set { state with
237229
stA := stA', lastRhoB := none, lastKeyB := none,
238230
correct := state.correct && ok, lastAction := some .recvA }
239231
else pure ()
240232

241-
/-- **O-Recv-B.** Deliver pending message `ρ` from A to B:
242-
`(keyB, stB') ← recvB(stB, ρ)`; assert `keyB = lastKeyA`
243-
(updating `correct`); clear pending `(lastRhoA, lastKeyA)`. -/
233+
/-- **O-Recv-B.** `tB++; (keyB, stB') ← recvB(stB, ρ)`; assert `keyB = lastKeyA`.
234+
Following [ACD19, Fig. 3], recv also advances the counter. -/
244235
def oracleRecvB [DecidableEq I] (cka : CKAScheme ProbComp IK St I Rho) :
245236
QueryImpl (Unit →ₒ Unit) (StateT (GameState St I Rho) ProbComp) :=
246237
fun () => do
247238
let state ← get
248-
-- Guard: alternating ok
249239
if validStep state.lastAction .recvB then
250-
-- ρ := lastRhoA (pending A → B message)
240+
-- tB++ (before protocol logic, matching paper)
241+
let state := { state with tB := state.tB + 1 }
251242
match state.lastRhoA with
252243
| none => pure ()
253244
| some ρ =>
254-
-- (keyB, stB') ← recvB(stB, ρ)
255245
match cka.recvB state.stB ρ with
256246
| none => pure ()
257247
| some (keyB, stB') =>
258-
-- ok := (keyB = lastKeyA)
259248
let ok := match state.lastKeyA with
260249
| some keyA => decide (some keyB = some keyA)
261250
| none => false
262-
-- stB ← stB', correct ← correct ∧ ok, clear pending
263251
set { state with
264252
stB := stB', lastRhoA := none, lastKeyA := none,
265253
correct := state.correct && ok, lastAction := some .recvB }
266254
else pure ()
267255

268256
/-! ### Challenge oracles -/
269257

270-
/-- **O-Chall-A.** Like `O-Send-A` but returns `b ? $ᵗ I : key` (real or
271-
random key). Only fires when `challengedParty = .A` and `tA = tStar`. -/
258+
/-- **O-Chall-A.** `tA++; req tA = t*; (key, ρ, stA') ← sendA(stA)`;
259+
return `(ρ, b ? $ᵗ I : key)`. Counter advances before the epoch check,
260+
matching [ACD19, Fig. 3]. -/
272261
def oracleChallA [SampleableType I] (cka : CKAScheme ProbComp IK St I Rho) :
273262
QueryImpl (Unit →ₒ Option (Rho × I)) (StateT (GameState St I Rho) ProbComp) :=
274263
fun () => do
275264
let state ← get
276-
-- Guard: challengedParty = A ∧ alternating ok ∧ tA = t*
277-
if state.challengedParty == .A &&
278-
validStep state.lastAction .challA && state.tA == state.tStar then
279-
-- (key, ρ, stA') ← sendA(stA)
280-
match ← liftM (cka.sendA state.stA) with
281-
| none => pure none
282-
| some (key, ρ, stA') =>
283-
-- outKey := b ? $ᵗ I : key
284-
let outKey ← if state.b then liftM ($ᵗ I : ProbComp I) else pure key
285-
-- stA ← stA', tA ← tA + 1
286-
set { state with
287-
stA := stA', lastRhoA := some ρ, lastKeyA := some key,
288-
lastAction := some .challA, tA := state.tA + 1 }
289-
-- return (ρ, outKey) to adversary
290-
return some (ρ, outKey)
265+
if validStep state.lastAction .challA then
266+
-- tA++ (before epoch check, matching paper)
267+
let state := { state with tA := state.tA + 1 }
268+
if state.challengedParty == .A && state.tA == state.tStar then
269+
match ← liftM (cka.sendA state.stA) with
270+
| none => pure none
271+
| some (key, ρ, stA') =>
272+
let outKey ← if state.b then liftM ($ᵗ I : ProbComp I) else pure key
273+
set { state with
274+
stA := stA', lastRhoA := some ρ, lastKeyA := some key,
275+
lastAction := some .challA }
276+
return some (ρ, outKey)
277+
else pure none
291278
else pure none
292279

293-
/-- **O-Chall-B.** Like `O-Send-B` but returns `b ? $ᵗ I : key` (real or
294-
random key). Only fires when `challengedParty = .B` and `tB = tStar`. -/
280+
/-- **O-Chall-B.** `tB++; req tB = t*; (key, ρ, stB') ← sendB(stB)`;
281+
return `(ρ, b ? $ᵗ I : key)`. Counter advances before the epoch check,
282+
matching [ACD19, Fig. 3]. -/
295283
def oracleChallB [SampleableType I] (cka : CKAScheme ProbComp IK St I Rho) :
296284
QueryImpl (Unit →ₒ Option (Rho × I)) (StateT (GameState St I Rho) ProbComp) :=
297285
fun () => do
298286
let state ← get
299-
-- Guard: challengedParty = B ∧ alternating ok ∧ tB = t*
300-
if state.challengedParty == .B &&
301-
validStep state.lastAction .challB && state.tB == state.tStar then
302-
-- (key, ρ, stB') ← sendB(stB)
303-
match ← liftM (cka.sendB state.stB) with
304-
| none => pure none
305-
| some (key, ρ, stB') =>
306-
-- outKey := b ? $ᵗ I : key
307-
let outKey ← if state.b then liftM ($ᵗ I : ProbComp I) else pure key
308-
-- stB ← stB', tB ← tB + 1
309-
set { state with
310-
stB := stB', lastRhoB := some ρ, lastKeyB := some key,
311-
lastAction := some .challB, tB := state.tB + 1 }
312-
-- return (ρ, outKey) to adversary
313-
return some (ρ, outKey)
287+
if validStep state.lastAction .challB then
288+
-- tB++ (before epoch check, matching paper)
289+
let state := { state with tB := state.tB + 1 }
290+
if state.challengedParty == .B && state.tB == state.tStar then
291+
match ← liftM (cka.sendB state.stB) with
292+
| none => pure none
293+
| some (key, ρ, stB') =>
294+
let outKey ← if state.b then liftM ($ᵗ I : ProbComp I) else pure key
295+
set { state with
296+
stB := stB', lastRhoB := some ρ, lastKeyB := some key,
297+
lastAction := some .challB }
298+
return some (ρ, outKey)
299+
else pure none
314300
else pure none
315301

316302
/-! ### Corruption oracles
317303
318304
Following [ACD19, Def. 13, Fig. 3], corruption is allowed iff `allowCorr ∨ finished`:
319305
- `allowCorr` : `max(tA, tB) + 2 ≤ tStar` (before the challenge window)
320306
- `finishedP` : `tP ≥ tStar + ΔCKA` (state healed after the challenge)
307+
308+
All counter values in these predicates are **post-increment**: every oracle
309+
(send, recv, chall) advances `tP` at the start, before any protocol logic.
321310
-/
322311

323-
/-- Challenge fires when the challenged party's counter reaches `tStar`. -/
312+
/-- Challenge fires when the challenged party's post-increment counter
313+
reaches `tStar`. Used by the reduction oracles in `Security.lean`;
314+
the generic chall oracles in `Defs.lean` inline this check. -/
324315
def isChallengeEpoch (state : GameState St I Rho) : Bool :=
325316
state.tP state.challengedParty == state.tStar
326317

327-
/-- The other party's send just before the challenge. Due to alternating
328-
communication with A going first:
318+
/-- The other party's send just before the challenge (post-increment check).
319+
Due to alternating communication with A going first:
329320
- challenging A: B-send at `tB = tStar - 1`
330321
- challenging B: A-send at `tA = tStar` -/
331322
def isOtherSendBeforeChall (state : GameState St I Rho) : Bool :=
@@ -352,7 +343,6 @@ def oracleCorruptA (St I Rho : Type) :
352343
QueryImpl (Unit →ₒ Option St) (StateT (GameState St I Rho) ProbComp) :=
353344
fun () => do
354345
let state ← get
355-
-- Guard: max(tA, tB) + 2 ≤ t* ∨ tA > t* + ΔCKA
356346
if allowCorr state || finishedA state then return some state.stA
357347
else return none
358348

@@ -361,7 +351,6 @@ def oracleCorruptB (St I Rho : Type) :
361351
QueryImpl (Unit →ₒ Option St) (StateT (GameState St I Rho) ProbComp) :=
362352
fun () => do
363353
let state ← get
364-
-- Guard: max(tA, tB) + 2 ≤ t* ∨ tB > t* + ΔCKA
365354
if allowCorr state || finishedB state then return some state.stB
366355
else return none
367356

0 commit comments

Comments
 (0)