Theory Unpredictable_Function
subsection ‹Unpredictable function›
theory Unpredictable_Function imports
Guessing_Many_One
begin
locale upf =
fixes key_gen :: "'key spmf"
and hash :: "'key ⇒ 'x ⇒ 'hash"
begin
type_synonym ('x', 'hash') adversary = "(unit, 'x' + ('x' × 'hash'), 'hash' + unit) gpv"
definition oracle_hash :: "'key ⇒ ('x, 'hash, 'x set) callee"
where
"oracle_hash k = (λL y. do {
let t = hash k y;
let L = insert y L;
return_spmf (t, L)
})"
definition oracle_flag :: "'key ⇒ ('x × 'hash, unit, bool × 'x set) callee"
where
"oracle_flag = (λkey (flg, L) (y, t).
return_spmf ((), (flg ∨ (t = (hash key y) ∧ y ∉ L), L)))"
abbreviation "oracle" :: "'key ⇒ ('x + 'x × 'hash, 'hash + unit, bool × 'x set) callee"
where "oracle key ≡ †(oracle_hash key) ⊕⇩O oracle_flag key"
definition game :: "('x, 'hash) adversary ⇒ bool spmf"
where
"game 𝒜 = do {
key ← key_gen;
(_, (flag', L')) ← exec_gpv (oracle key) 𝒜 (False, {});
return_spmf flag'
}"
definition advantage :: "('x, 'hash) adversary ⇒ real"
where "advantage 𝒜 = spmf (game 𝒜) True"
type_synonym ('x', 'hash') adversary1 = "('x' × 'hash', 'x', 'hash') gpv"
definition game1 :: "('x, 'hash) adversary1 ⇒ bool spmf"
where
"game1 𝒜 = do {
key ← key_gen;
((m, h), L) ← exec_gpv (oracle_hash key) 𝒜 {};
return_spmf (h = hash key m ∧ m ∉ L)
}"
definition advantage1 :: "('x, 'hash) adversary1 ⇒ real"
where "advantage1 𝒜 = spmf (game1 𝒜) True"
lemma advantage_advantage1:
assumes bound: "interaction_bounded_by (Not ∘ isl) 𝒜 q"
shows "advantage 𝒜 ≤ advantage1 (guessing_many_one.reduction q (λ_ :: unit. 𝒜) ()) * q"
proof -
let ?init = "map_spmf (λkey. (key, (), {})) key_gen"
let ?oracle = "λkey . oracle_hash key"
let ?eval = "λkey (_ :: unit) L (x, h). return_spmf (h = hash key x ∧ x ∉ L)"
interpret guessing_many_one ?init ?oracle ?eval .
have [simp]: "oracle_flag key = eval_oracle key ()" for key
by(simp add: oracle_flag_def eval_oracle_def fun_eq_iff)
have "game 𝒜 = game_multi (λ_. 𝒜)"
by(auto simp add: game_multi_def game_def bind_map_spmf intro!: bind_spmf_cong[OF refl])
hence "advantage 𝒜 = advantage_multi (λ_. 𝒜)" by(simp add: advantage_def advantage_multi_def)
also have "… ≤ advantage_single (reduction q (λ_. 𝒜)) * q" using bound
by(rule many_single_reduction)(auto simp add: oracle_hash_def)
also have "advantage_single (reduction q (λ_. 𝒜)) = advantage1 (reduction q (λ_. 𝒜) ())" for 𝒜
unfolding advantage1_def advantage_single_def
by(auto simp add: game1_def game_single_def bind_map_spmf o_def intro!: bind_spmf_cong[OF refl] arg_cong2[where f=spmf])
finally show ?thesis .
qed
end
end