text‹Concrete syntax: messages appear as ‹{A,B,NA}›, etc...› syntax "_MTuple" :: "['a, args] ==> 'a * 'b" (‹(‹indent=2 notation=‹mixfix message tuple››{_,/ _})›)
syntax_consts "_MTuple"⇌ MPair translations "{x, y, z}"⇌"{x, {y, z}}" "{x, y}"⇌"CONST MPair x y"
definition HPair :: "[msg,msg] => msg" (‹(4Hash[_] /_)› [0, 1000]) where
― ‹Message Y paired with a MAC computed with the help of X› "Hash[X] Y == { Hash{X,Y}, Y}"
definition keysFor :: "msg set => key set"where
― ‹Keys useful to decrypt elements of a message set› "keysFor H == invKey ` {K. ∃X. Crypt K X ∈ H}"
subsubsection‹Inductive Definition of All Parts" of a Message›
inductive_set
parts :: "msg set => msg set" for H :: "msg set" where
Inj [intro]: "X ∈ H ==> X ∈ parts H"
| Fst: "{X,Y}∈ parts H ==> X ∈ parts H"
| Snd: "{X,Y}∈ parts H ==> Y ∈ parts H"
| Body: "Crypt K X ∈ parts H ==> X ∈ parts H"
lemma parts_mono: "G ⊆ H ==> parts(G) ⊆ parts(H)" apply auto apply (erule parts.induct) apply (metis parts.Inj rev_subsetD) apply (metis parts.Fst) apply (metis parts.Snd) by (metis parts.Body)
text‹Equations hold because constructors are injective.› lemma Friend_image_eq [simp]: "(Friend x ∈ Friend`A) = (x∈A)" by (metis agent.inject image_iff)
lemma Key_image_eq [simp]: "(Key x ∈ Key`A) = (x ∈ A)" by (metis image_iff msg.inject(4))
lemma Nonce_Key_image_eq [simp]: "Nonce x ∉ Key`A" by (metis image_iff msg.distinct(23))
subsubsection‹Inverse of keys›
lemma invKey_eq [simp]: "(invKey K = invKey K') = (K = K')" by (metis invKey)
lemma Crypt_imp_invKey_keysFor: "Crypt K X ∈ H ==> invKey K ∈ keysFor H" by (unfold keysFor_def, blast)
subsection‹Inductive relation "parts"›
lemma MPair_parts: "[| {X,Y}∈ parts H; [| X ∈ parts H; Y ∈ parts H |] ==> P |] ==> P" by (blast dest: parts.Fst parts.Snd)
declare MPair_parts [elim!] parts.Body [dest!] text‹NB These two rules are UNSAFE in the formal sense, as they discard the
compound message. They work well on THIS FILE. ‹MPair_parts› is left as SAFE because it speeds up proofs.
The Crypt rule is normally kept UNSAFE to avoid breaking up certificates.›
lemma parts_increasing: "H ⊆ parts(H)" by blast
lemmas parts_insertI = subset_insertI [THEN parts_mono, THEN subsetD]
lemma parts_emptyE [elim!]: "X∈ parts{} ==> P" by simp
text‹WARNING: loops if H = {Y}, therefore must not be repeated!› lemma parts_singleton: "X∈ parts H ==> ∃Y∈H. X∈ parts {Y}" apply (erule parts.induct) apply fast+ done
lemma parts_insert: "parts (insert X H) = parts {X} ∪ parts H" apply (subst insert_is_Un [of _ H]) apply (simp only: parts_Un) done
lemma parts_insert2: "parts (insert X (insert Y H)) = parts {X} ∪ parts {Y} ∪ parts H" by (metis Un_commute Un_empty_left Un_empty_right Un_insert_left Un_insert_right parts_Un)
lemma parts_UN_subset1: "(∪x∈A. parts(H x)) ⊆ parts(∪x∈A. H x)" by (intro UN_least parts_mono UN_upper)
text‹This allows ‹blast› to simplify occurrences of term‹parts(G∪H)› in the assumption.› lemmas in_parts_UnE = parts_Un [THEN equalityD1, THEN subsetD, THEN UnE] declare in_parts_UnE [elim!]
lemma parts_insert_subset: "insert X (parts H) ⊆ parts(insert X H)" by (blast intro: parts_mono [THEN [2] rev_subsetD])
subsubsection‹Idempotence and transitivity›
lemma parts_partsD [dest!]: "X∈ parts (parts H) ==> X∈ parts H" by (erule parts.induct, blast+)
lemma parts_idem [simp]: "parts (parts H) = parts H" by blast
lemma parts_subset_iff [simp]: "(parts G ⊆ parts H) = (G ⊆ parts H)" apply (rule iffI) apply (metis Un_absorb1 Un_subset_iff parts_Un parts_increasing) apply (metis parts_idem parts_mono) done
lemma parts_trans: "[| X∈ parts G; G ⊆ parts H |] ==> X∈ parts H" by (blast dest: parts_mono)
lemma parts_cut: "[|Y∈ parts (insert X G); X∈ parts H|] ==> Y∈ parts(G ∪ H)" by (metis (no_types) Un_insert_left Un_insert_right insert_absorb le_supE
parts_Un parts_idem parts_increasing parts_trans)
subsubsection‹Rewrite rules for pulling out atomic messages›
text‹Inductive definition of "analz" -- what can be broken down from a set of
messages, including keys. A form of downward closure. Pairs can
be taken apart; messages decrypted with known keys.›
inductive_set
analz :: "msg set => msg set" for H :: "msg set" where
Inj [intro,simp] : "X ∈ H ==> X ∈ analz H"
| Fst: "{X,Y}∈ analz H ==> X ∈ analz H"
| Snd: "{X,Y}∈ analz H ==> Y ∈ analz H"
| Decrypt [dest]: "[|Crypt K X ∈ analz H; Key(invKey K) ∈ analz H|] ==> X ∈ analz H"
text‹Making it safe speeds up proofs› lemma MPair_analz [elim!]: "[| {X,Y}∈ analz H; [| X ∈ analz H; Y ∈ analz H |] ==> P |] ==> P" by (blast dest: analz.Fst analz.Snd)
lemma analz_increasing: "H ⊆ analz(H)" by blast
lemma analz_subset_parts: "analz H ⊆ parts H" apply (rule subsetI) apply (erule analz.induct, blast+) done
text‹Converse fails: we can analz more from the union than from the
separate parts, as a key in one might decrypt a message in the other› lemma analz_Un: "analz(G) ∪ analz(H) ⊆ analz(G ∪ H)" by (intro Un_least analz_mono Un_upper1 Un_upper2)
lemma analz_insert: "insert X (analz H) ⊆ analz(insert X H)" by (blast intro: analz_mono [THEN [2] rev_subsetD])
subsubsection‹Rewrite rules for pulling out atomic messages›
text‹Can pull out enCrypted message if the Key is not known› lemma analz_insert_Crypt: "Key (invKey K) ∉ analz H ==> analz (insert (Crypt K X) H) = insert (Crypt K X) (analz H)" apply (rule analz_insert_eq_I) apply (erule analz.induct, auto)
done
lemma lemma1: "Key (invKey K) ∈ analz H ==> analz (insert (Crypt K X) H) ⊆ insert (Crypt K X) (analz (insert X H))" apply (rule subsetI) apply (erule_tac x = x in analz.induct, auto) done
lemma lemma2: "Key (invKey K) ∈ analz H ==> insert (Crypt K X) (analz (insert X H)) ⊆ analz (insert (Crypt K X) H)" apply auto apply (erule_tac x = x in analz.induct, auto) apply (blast intro: analz_insertI analz.Decrypt) done
lemma analz_insert_Decrypt: "Key (invKey K) ∈ analz H ==> analz (insert (Crypt K X) H) = insert (Crypt K X) (analz (insert X H))" by (intro equalityI lemma1 lemma2)
text‹Case analysis: either the message is secure, or it is not! Effective,
can cause subgoals to blow up! Use with ‹if_split›; apparently ‹split_tac› does not cope with patterns such as term‹analz (insert
Crypt K X) H)›› lemma analz_Crypt_if [simp]: "analz (insert (Crypt K X) H) = (if (Key (invKey K) ∈ analz H) then insert (Crypt K X) (analz (insert X H)) else insert (Crypt K X) (analz H))" by (simp add: analz_insert_Crypt analz_insert_Decrypt)
text‹This rule supposes "for the sake of argument" that we have the key.› lemma analz_insert_Crypt_subset: "analz (insert (Crypt K X) H) ⊆ insert (Crypt K X) (analz (insert X H))" apply (rule subsetI) apply (erule analz.induct, auto) done
lemma analz_trans: "[| X∈ analz G; G ⊆ analz H |] ==> X∈ analz H" by (drule analz_mono, blast)
declare analz_trans[intro]
lemma analz_cut: "[| Y∈ analz (insert X H); X∈ analz H |] ==> Y∈ analz H" by (metis analz_idem analz_increasing analz_mono insert_absorb insert_mono insert_subset)
text‹This rewrite rule helps in the simplification of messages that involve
the forwarding of unknown components (X). Without it, removing occurrences
of X can be very complicated.› lemma analz_insert_eq: "X∈ analz H ==> analz (insert X H) = analz H" by (blast intro: analz_cut analz_insertI)
lemma analz_cong: "[| analz G = analz G'; analz H = analz H' |] ==> analz (G ∪ H) = analz (G' ∪ H')" by (intro equalityI analz_subset_cong, simp_all)
lemma analz_insert_cong: "analz H = analz H' ==> analz(insert X H) = analz(insert X H')" by (force simp only: insert_def intro!: analz_cong)
text‹If there are no pairs or encryptions then analz does nothing› lemma analz_trivial: "[| ∀X Y. {X,Y}∉ H; ∀X K. Crypt K X ∉ H |] ==> analz H = H" apply safe apply (erule analz.induct, blast+) done
subsection‹Inductive relation "synth"›
text‹Inductive definition of "synth" -- what can be built up from a set of
messages. A form of upward closure. Pairs can be built, messages
encrypted with known keys. Agent names are public domain.
Numbers can be guessed, but Nonces cannot be.›
inductive_set
synth :: "msg set => msg set" for H :: "msg set" where
Inj [intro]: "X ∈ H ==> X ∈ synth H"
| Agent [intro]: "Agent agt ∈ synth H"
| Number [intro]: "Number n ∈ synth H"
| Hash [intro]: "X ∈ synth H ==> Hash X ∈ synth H"
| MPair [intro]: "[|X ∈ synth H; Y ∈ synth H|] ==> {X,Y}∈ synth H"
| Crypt [intro]: "[|X ∈ synth H; Key(K) ∈ H|] ==> Crypt K X ∈ synth H"
text‹NO ‹Agent_synth›, as any Agent name can be synthesized.
The same holds for term‹Number›› inductive_cases Nonce_synth [elim!]: "Nonce n ∈ synth H" inductive_cases Key_synth [elim!]: "Key K ∈ synth H" inductive_cases Hash_synth [elim!]: "Hash X ∈ synth H" inductive_cases MPair_synth [elim!]: "{X,Y}∈ synth H" inductive_cases Crypt_synth [elim!]: "Crypt K X ∈ synth H"
lemma synth_increasing: "H ⊆ synth(H)" by blast
subsubsection‹Unions›
text‹Converse fails: we can synth more from the union than from the
separate parts, building a compound message using elements of each.› lemma synth_Un: "synth(G) ∪ synth(H) ⊆ synth(G ∪ H)" by (intro Un_least synth_mono Un_upper1 Un_upper2)
lemma synth_insert: "insert X (synth H) ⊆ synth(insert X H)" by (metis insert_iff insert_subset subset_insertI synth.Inj synth_mono)
subsubsection‹For reasoning about the Fake rule in traces›
lemma parts_insert_subset_Un: "X ∈ G ==> parts(insert X H) ⊆ parts G ∪ parts H" proof - assume"X ∈ G" hence"∀x1. G ⊆ x1⟶ X ∈ x1 "by auto hence"∀x1. X ∈ G ∪ x1"by (metis Un_upper1) hence"insert X H ⊆ G ∪ H"by (metis Un_upper2 insert_subset) hence"parts (insert X H) ⊆ parts (G ∪ H)"by (metis parts_mono) thus"parts (insert X H) ⊆ parts G ∪ parts H"by (metis parts_Un) qed
lemma Fake_parts_insert: "X ∈ synth (analz H) ==> parts (insert X H) ⊆ synth (analz H) ∪ parts H" proof - assume A1: "X ∈ synth (analz H)" have F1: "∀x1. analz x1∪ synth (analz x1) = analz (synth (analz x1))" by (metis analz_idem analz_synth) have F2: "∀x1. parts x1∪ synth (analz x1) = parts (synth (analz x1))" by (metis parts_analz parts_synth) have F3: "X ∈ synth (analz H)"using A1 by metis have"∀x2 x1::msg set. x1≤ sup x1 x2"by (metis inf_sup_ord(3)) hence F4: "∀x1. analz x1⊆ analz (synth x1)"by (metis analz_synth) have F5: "X ∈ synth (analz H)"using F3 by metis have"∀x1. analz x1⊆ synth (analz x1) ⟶ analz (synth (analz x1)) = synth (analz x1)" using F1 by (metis subset_Un_eq) hence F6: "∀x1. analz (synth (analz x1)) = synth (analz x1)" by (metis synth_increasing) have"∀x1. x1⊆ analz (synth x1)"using F4 by (metis analz_subset_iff) hence"∀x1. x1⊆ analz (synth (analz x1))"by (metis analz_subset_iff) hence"∀x1. x1⊆ synth (analz x1)"using F6 by metis hence"H ⊆ synth (analz H)"by metis hence"H ⊆ synth (analz H) ∧ X ∈ synth (analz H)"using F5 by metis hence"insert X H ⊆ synth (analz H)"by (metis insert_subset) hence"parts (insert X H) ⊆ parts (synth (analz H))"by (metis parts_mono) hence"parts (insert X H) ⊆ parts H ∪ synth (analz H)"using F2 by metis thus"parts (insert X H) ⊆ synth (analz H) ∪ parts H"by (metis Un_commute) qed
lemma Fake_parts_insert_in_Un: "[|Z ∈ parts (insert X H); X ∈ synth (analz H)|] ==> Z ∈ synth (analz H) ∪ parts H" by (blast dest: Fake_parts_insert [THEN subsetD, dest])
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.