(* Title: HOL/Auth/Public.thy Author: Lawrence C Paulson, Cambridge University Computer Laboratory Copyright 1996 University of Cambridge Theory of Public Keys (common to all public-key protocols) Private and public keys; initial states of agents *)
theory Public imports Event begin
lemma invKey_K: "K ∈ symKeys ==> invKey K = K" by (simp add: symKeys_def)
text‹By freeness of agents, no two agents have the same key. Since 🍋‹True≠False›, specification (publicKey)
injective_publicKey: "publicKey b A = publicKey c A' ==> b=c ∧ A=A'" apply (rule exI [of _ "λb A. 2 * case_agent 0 (λn. n + 2) 1 A + case_keymode 0 1 b"]) apply (auto simp add: inj_on_def split: agent.split keymode.split) apply presburger apply presburger done
axiomatizationwhere (*No private key equals any public key (essential to ensure that private keys are private!) *)
privateKey_neq_publicKey [iff]: "privateKey b A ≠ publicKey c A'"
lemma priEK_noteq_shrK [simp]: "priEK A ≠ shrK B" by auto
lemma publicKey_notin_image_shrK [simp]: "publicKey b x ∉ shrK ` AA" by auto
lemma privateKey_notin_image_shrK [simp]: "privateKey b x ∉ shrK ` AA" by auto
lemma shrK_notin_image_publicKey [simp]: "shrK x ∉ publicKey b ` AA" by auto
lemma shrK_notin_image_privateKey [simp]: "shrK x ∉ invKey ` publicKey b ` AA" by auto
lemma shrK_image_eq [simp]: "(shrK x ∈ shrK ` AA) = (x ∈ AA)" by auto
text‹For some reason, moving this up can make some proofs loop!› declare invKey_K [simp]
subsection‹Initial States of Agents›
text‹Note: for all practical purposes, all that matters is the initial knowledge of the Spy. All other agents are automata, merely following the protocol.›
overloading
initState ≡ initState begin
primrec initState where (*Agents know their private key and all public keys*)
initState_Server: "initState Server = {Key (priEK Server), Key (priSK Server)} ∪ (Key ` range pubEK) ∪ (Key ` range pubSK) ∪ (Key ` range shrK)"
text‹These lemmas allow reasoning about 🍋‹used evs› rather than 🍋‹knows Spy evs›, which is useful when there are private Notes.
Because they depend upon the definition of 🍋‹initState›, they cannot
be moved up.›
lemma MPair_used_D: "{X,Y}∈ used H ==> X ∈ used H ∧ Y ∈ used H" by (drule used_parts_subset_parts, simp, blast)
text‹There was a similar theorem in Event.thy, so perhaps this one can be moved up if proved directly by induction.› lemma MPair_used [elim!]: "[{X,Y}∈ used H; [X ∈ used H; Y ∈ used H]==> P] ==> P" by (blast dest: MPair_used_D)
text‹Rewrites should not refer to 🍋‹initState(Friend i)› because
that expression is not in normal form.›
lemma Crypt_notin_initState: "Crypt K X ∉ parts (initState B)" by (induct B, auto)
lemma Crypt_notin_used_empty [simp]: "Crypt K X ∉ used []" by (simp add: Crypt_notin_initState used_Nil)
(*** Basic properties of shrK ***)
(*Agents see their own shared keys!*) lemma shrK_in_initState [iff]: "Key (shrK A) ∈ initState A" by (induct_tac "A", auto)
lemma shrK_in_knows [iff]: "Key (shrK A) ∈ knows A evs" by (simp add: initState_subset_knows [THEN subsetD])
lemma shrK_in_used [iff]: "Key (shrK A) ∈ used evs" by (rule initState_into_used, blast)
(** Fresh keys never clash with long-term shared keys **)
(*Used in parts_induct_tac and analz_Fake_tac to distinguish session keys from long-term shared keys*) lemma Key_not_used [simp]: "Key K ∉ used evs ==> K ∉ range shrK" by blast
lemma shrK_neq: "Key K ∉ used evs ==> shrK B ≠ K" by blast
text‹Spy sees private keys of bad agents!› lemma Spy_spies_bad_privateKey [intro!]: "A ∈ bad ==> Key (privateKey b A) ∈ spies evs" apply (induct_tac "evs") apply (auto simp add: imageI knows_Cons split: event.split) done
text‹Spy sees long-term shared keys of bad agents!› lemma Spy_spies_bad_shrK [intro!]: "A ∈ bad ==> Key (shrK A) ∈ spies evs" apply (induct_tac "evs") apply (simp_all add: imageI knows_Cons split: event.split) done
lemma publicKey_into_used [iff] :"Key (publicKey b A) ∈ used evs" apply (rule initState_into_used) apply (rule publicKey_in_initState [THEN parts.Inj]) done
lemma privateKey_into_used [iff]: "Key (privateKey b A) ∈ used evs" apply(rule initState_into_used) apply(rule priK_in_initState [THEN parts.Inj]) done
(*For case analysis on whether or not an agent is compromised*) lemma Crypt_Spy_analz_bad: "[Crypt (shrK A) X ∈ analz (knows Spy evs); A ∈ bad] ==> X ∈ analz (knows Spy evs)" by force
subsection‹Fresh Nonces›
lemma Nonce_notin_initState [iff]: "Nonce N ∉ parts (initState B)" by (induct_tac "B", auto)
lemma Nonce_notin_used_empty [simp]: "Nonce N ∉ used []" by (simp add: used_Nil)
subsection‹Supply fresh nonces for possibility theorems›
text‹In any trace, there is an upper bound N on the greatest nonce in use› lemma Nonce_supply_lemma: "∃N. ∀n. N≤n ⟶ Nonce n ∉ used evs" apply (induct_tac "evs") apply (rule_tac x = 0 in exI) apply (simp_all (no_asm_simp) add: used_Cons split: event.split) apply safe apply (rule msg_Nonce_supply [THEN exE], blast elim!: add_leE)+ done
lemma Nonce_supply1: "∃N. Nonce N ∉ used evs" by (rule Nonce_supply_lemma [THEN exE], blast)
lemma Nonce_supply: "Nonce (SOME N. Nonce N ∉ used evs) ∉ used evs" apply (rule Nonce_supply_lemma [THEN exE]) apply (rule someI, fast) done
subsection‹Specialized Rewriting for Theorems About 🍋‹analz› and Image›
lemma insert_Key_singleton: "insert (Key K) H = Key ` {K} ∪ H" by blast
lemma insert_Key_image: "insert (Key K) (Key`KK ∪ C) = Key ` (insert K KK) ∪ C" by blast
lemma Crypt_imp_keysFor :"[Crypt K X ∈ H; K ∈ symKeys]==> K ∈ keysFor H" by (drule Crypt_imp_invKey_keysFor, simp)
text‹Lemma for the trivial direction of the if-and-only-if of the Session Key Compromise Theorem› lemma analz_image_freshK_lemma: "(Key K ∈ analz (Key`nE ∪ H)) ⟶ (K ∈ nE | Key K ∈ analz H) ==> (Key K ∈ analz (Key`nE ∪ H)) = (K ∈ nE | Key K ∈ analz H)" by (blast intro: analz_mono [THEN [2] rev_subsetD])
lemmas analz_image_freshK_simps =
simp_thms mem_simps 🍋‹these two allow its use with ‹only:›\
disj_comms
image_insert [THEN sym] image_Un [THEN sym] empty_subsetI insert_subset
analz_insert_eq Un_upper2 [THEN analz_mono, THEN subsetD]
insert_Key_singleton
Key_not_used insert_Key_image Un_assoc [THEN sym]
ML ‹ structure Public = struct val analz_image_freshK_ss = simpset_of (🍋 |> Simplifier.del_simps @{thms image_insert image_Un} |> Simplifier.del_simps @{thms imp_disjL} (*reduces blow-up*)
|> Simplifier.add_simps @{thms analz_image_freshK_simps})
(*Tactic for possibility theorems*) fun possibility_tac ctxt =
REPEAT (*omit used_Says so that Nonces start from different traces!*)
(ALLGOALS (simp_tac (ctxt |> Simplifier.set_unsafe_solver safe_solver |> Simplifier.del_simp @{thm used_Says})) THEN
REPEAT_FIRST (eq_assume_tac ORELSE'
resolve_tac ctxt [refl, conjI, @{thm Nonce_supply}]))
(*For harder protocols (such as Recur) where we have to set up some nonces and keys initially*) fun basic_possibility_tac ctxt =
REPEAT
(ALLGOALS (asm_simp_tac (ctxt |> Simplifier.set_unsafe_solver safe_solver)) THEN
REPEAT_FIRST (resolve_tac ctxt [refl, conjI]))
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.