intuition.
unfold randomFunc.
case_eq (f#d); intuition; wftac.
Qed.
Hint Resolve randomFunc_wf : wftac.
(* Eager random functions with finite domain *)
Definition RndFunc(lsd : list D) : Comp (list (D * R)) :=
compFold _ (fun f d => r <-$ RndR; ret (d, r)::f) nil lsd.
End RandomFunc.
Local Open Scope type_scope.
Local Open Scope comp_scope.
Section PRF_concrete.
Variable D R Key : Set.
Variable RndKey : Comp Key.
Variable RndR : Comp R.
Variable f : Key -> D -> R.
Hypothesis D_EqDec : EqDec D.
Hypothesis R_EqDec : EqDec R.
Definition RndR_func : (list (D * R) -> D -> Comp (R * list (D * R))) :=
(randomFunc RndR _).
Section PRF_NA_concrete.
(* A PRF that is secure against a non-adaptive adversary. *)
Variable State : Set.
Variable A1 : Comp (list D * State).
Variable A2 : State -> list R -> Comp bool.
Definition PRF_NA_G_A : Comp bool :=
[lsD, s_A] <-$2 A1;
lsR <-$ (k <-$ RndKey; ret (map (f k) lsD));
A2 s_A lsR.
Definition PRF_NA_G_B : Comp bool :=
[lsD, s_A] <-$2 A1;
[lsR, _] <-$2 oracleMap _ _ RndR_func nil lsD;
A2 s_A lsR.
Definition PRF_NA_Advantage :=
| Pr[PRF_NA_G_A] - Pr[PRF_NA_G_B] |.
End PRF_NA_concrete.
Section PRF_NAI_concrete.
Variable A_state : Set.
Variable A1 : Comp ((list (list D)) * A_state).
Variable A2 : A_state -> list (list R) -> Comp bool.
Definition PRF_NAI_G0 :=
[lsDs, s_A] <-$2 A1;
lsRs <-$ compMap _ (fun lsD => k <-$ RndKey; ret (map (f k) lsD)) lsDs;
A2 s_A lsRs.
Definition PRF_NAI_G1 :=
[lsDs, s_A] <-$2 A1;
lsRs <-$ compMap _ (fun lsD => [lsR, _] <-$2 oracleMap _ _ RndR_func nil lsD; ret lsR) lsDs;
A2 s_A lsRs.
Definition PRF_NAI_Advantage :=
| Pr[PRF_NAI_G0] - Pr[PRF_NAI_G1] |.
Section PRF_NA_impl_NAI.
Variable maxLists : nat.
Hypothesis maxLists_correct :
forall ls s_A,
In (ls, s_A) (getSupport A1) ->
(length ls <= maxLists)%nat.
Hypothesis A_state_EqDec : EqDec A_state.
Hypothesis RndR_wf : well_formed_comp RndR.
Hypothesis RndKey_wf : well_formed_comp RndKey.
Variable maxDistance : Rat.
Hypothesis maxDistance_correct :
forall i,
PRF_NA_Advantage (B1 nil _ _ A1 i) (B2 (fun lsD => k <-$ RndKey; ret (map (f k) lsD))
(fun lsD => [lsR, _] <-$2 oracleMap _ _ RndR_func nil lsD; ret lsR)
_ A2) <= maxDistance.

(* Specifications: *)
Theorem PRF_NAI_Advantage_eq_Hybrid:
PRF_NAI_Advantage == ListHybrid_Advantage
(fun lsD => k <-$ RndKey; ret (map (f k) lsD))
(fun lsD => [lsR, _] <-$2 oracleMap _ _ RndR_func nil lsD; ret lsR)
_ A1 A2.