text‹The constant "spies" is retained for compatibility's sake›
primrec
knows :: "agent ==> event list ==> msg set" where
knows_Nil: "knows A [] = initState A"
| knows_Cons: "knows A (ev # evs) = (if A = Spy then (case ev of Says A' B X ==> insert X (knows Spy evs) | Gets A' X ==> knows Spy evs | Notes A' X ==> if A' ∈ bad then insert X (knows Spy evs) else knows Spy evs) else (case ev of Says A' B X ==> if A'=A then insert X (knows A evs) else knows A evs | Gets A' X ==> if A'=A then insert X (knows A evs) else knows A evs | Notes A' X ==> if A'=A then insert X (knows A evs) else knows A evs))"
text‹Spy has access to his own key for spoof messages, but Server is secure› specification (bad)
Spy_in_bad [iff]: "Spy ∈ bad"
Server_not_bad [iff]: "Server ∉ bad" by (rule exI [of _ "{Spy}"], simp)
primrec (*Set of items that might be visible to somebody:
complement of the set of fresh items*)
used :: "event list ==> msg set" where
used_Nil: "used [] = (UN B. parts (initState B))"
| used_Cons: "used (ev # evs) = (case ev of Says A B X ==> parts {X} ∪ used evs | Gets A X ==> used evs | Notes A X ==> parts {X} ∪ used evs)"
― ‹The case for term‹Gets› seems anomalous, but term‹Gets› always
follows term‹Says› in real protocols. Seems difficult to change.
See 🪙‹Gets_correct› in theory 🪙‹Guard/Extensions.thy›.›
lemma Notes_imp_used [rule_format]: "Notes A X ∈ set evs ⟶ X ∈ used evs" apply (induct_tac evs) apply (auto split: event.split) done
lemma Says_imp_used [rule_format]: "Says A B X ∈ set evs ⟶ X ∈ used evs" apply (induct_tac evs) apply (auto split: event.split) done
subsection‹Function term‹knows››
(*Simplifying parts(insertX(knowsSpyevs))=parts{X}\<union>parts(knowsSpyevs).
This version won't loop with the simplifier.*) lemmas parts_insert_knows_A = parts_insert [of _ "knows A evs"] for A evs
lemma knows_Spy_Says [simp]: "knows Spy (Says A B X # evs) = insert X (knows Spy evs)" by simp
text‹Letting the Spy see "bad" agents' notes avoids redundant case-splits
on whether term‹A=Spy› and whether term‹A∈bad›› lemma knows_Spy_Notes [simp]: "knows Spy (Notes A X # evs) = (if A∈bad then insert X (knows Spy evs) else knows Spy evs)" by simp
lemma knows_Spy_Gets [simp]: "knows Spy (Gets A X # evs) = knows Spy evs" by simp
lemma knows_Spy_subset_knows_Spy_Says: "knows Spy evs ⊆ knows Spy (Says A B X # evs)" by (simp add: subset_insertI)
lemma knows_Spy_subset_knows_Spy_Notes: "knows Spy evs ⊆ knows Spy (Notes A X # evs)" by force
lemma knows_Spy_subset_knows_Spy_Gets: "knows Spy evs ⊆ knows Spy (Gets A X # evs)" by (simp add: subset_insertI)
text‹Spy sees what is sent on the traffic› lemma Says_imp_knows_Spy [rule_format]: "Says A B X ∈ set evs ⟶ X ∈ knows Spy evs" apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) done
lemma Notes_imp_knows_Spy [rule_format]: "Notes A X ∈ set evs ⟶ A ∈ bad ⟶ X ∈ knows Spy evs" apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) done
text‹Elimination rules: derive contradictions from old Says events containing
items known to be fresh› lemmas knows_Spy_partsEs =
Says_imp_knows_Spy [THEN parts.Inj, elim_format]
parts.Body [elim_format]
text‹Compatibility for the old "spies" function› lemmas spies_partsEs = knows_Spy_partsEs lemmas Says_imp_spies = Says_imp_knows_Spy lemmas parts_insert_spies = parts_insert_knows_A [of _ Spy]
subsection‹Knowledge of Agents›
lemma knows_Says: "knows A (Says A B X # evs) = insert X (knows A evs)" by simp
lemma knows_Notes: "knows A (Notes A X # evs) = insert X (knows A evs)" by simp
lemma knows_Gets: "A ≠ Spy ⟶ knows A (Gets A X # evs) = insert X (knows A evs)" by simp
lemma knows_subset_knows_Says: "knows A evs ⊆ knows A (Says A' B X # evs)" by (simp add: subset_insertI)
lemma knows_subset_knows_Notes: "knows A evs ⊆ knows A (Notes A' X # evs)" by (simp add: subset_insertI)
lemma knows_subset_knows_Gets: "knows A evs ⊆ knows A (Gets A' X # evs)" by (simp add: subset_insertI)
text‹Agents know what they say› lemma Says_imp_knows [rule_format]: "Says A B X ∈ set evs ⟶ X ∈ knows A evs" apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) apply blast done
text‹Agents know what they note› lemma Notes_imp_knows [rule_format]: "Notes A X ∈ set evs ⟶ X ∈ knows A evs" apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) apply blast done
text‹Agents know what they receive› lemma Gets_imp_knows_agents [rule_format]: "A ≠ Spy ⟶ Gets A X ∈ set evs ⟶ X ∈ knows A evs" apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) done
text‹What agents DIFFERENT FROM Spy know
was either said, or noted, or got, or known initially› lemma knows_imp_Says_Gets_Notes_initState [rule_format]: "[| X ∈ knows A evs; A ≠ Spy |] ==> ∃B. Says A B X ∈ set evs ∨ Gets A X ∈ set evs ∨ Notes A X ∈ set evs ∨ X ∈ initState A" apply (erule rev_mp) apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) apply blast done
text‹What the Spy knows -- for the time being --
was either said or noted, or known initially› lemma knows_Spy_imp_Says_Notes_initState [rule_format]: "[| X ∈ knows Spy evs |] ==> ∃A B. Says A B X ∈ set evs ∨ Notes A X ∈ set evs ∨ X ∈ initState Spy" apply (erule rev_mp) apply (induct_tac "evs") apply (simp_all (no_asm_simp) split: event.split) apply blast done
text‹NOTE REMOVAL--laws above are cleaner, as they don't involve "case"› declare knows_Cons [simp del]
used_Nil [simp del] used_Cons [simp del]
text‹For proving theorems of the form term‹X ∉ analz (knows Spy evs) ⟶ P›
New events added by induction to "evs" are discarded. Provided
this information isn't needed, the proof will be much shorter, since
it will omit complicated reasoning about term‹analz›.›
lemmas analz_mono_contra =
knows_Spy_subset_knows_Spy_Says [THEN analz_mono, THEN contra_subsetD]
knows_Spy_subset_knows_Spy_Notes [THEN analz_mono, THEN contra_subsetD]
knows_Spy_subset_knows_Spy_Gets [THEN analz_mono, THEN contra_subsetD]
lemmas analz_impI = impI [where P = "Y ∉ analz (knows Spy evs)"] for Y evs
ML ‹
analz_mono_contra_tac ctxt =
resolve_tac ctxt @{thms analz_impI} THEN'
REPEAT1 o (dresolve_tac ctxt @{thms analz_mono_contra})
THEN' mp_tac ctxt ›
lemma knows_subset_knows_Cons: "knows A evs ⊆ knows A (e # evs)" by (induct e, auto simp: knows_Cons)
lemma initState_subset_knows: "initState A ⊆ knows A evs" apply (induct_tac evs, simp) apply (blast intro: knows_subset_knows_Cons [THEN subsetD]) done
text‹For proving ‹new_keys_not_used›› lemma keysFor_parts_insert: "[| K ∈ keysFor (parts (insert X G)); X ∈ synth (analz H) |] ==> K ∈ keysFor (parts (G ∪ H)) | Key (invKey K) ∈ parts H" by (force
dest!: parts_insert_subset_Un [THEN keysFor_mono, THEN [2] rev_subsetD]
analz_subset_parts [THEN keysFor_mono, THEN [2] rev_subsetD]
intro: analz_subset_parts [THEN subsetD] parts_mono [THEN [2] rev_subsetD])
method_setup analz_mono_contra = ‹
Scan.succeed (fn ctxt => SIMPLE_METHOD (REPEAT_FIRST (analz_mono_contra_tac ctxt)))› "for proving theorems of the form X ∉ analz (knows Spy evs) ⟶ P"
subsubsection‹Useful for case analysis on whether a hash is a spoof or not›
lemmas syan_impI = impI [where P = "Y ∉ synth (analz (knows Spy evs))"] for Y evs
method_setup synth_analz_mono_contra = ‹
Scan.succeed (fn ctxt => SIMPLE_METHOD (REPEAT_FIRST (synth_analz_mono_contra_tac ctxt)))› "for proving theorems of the form X ∉ synth (analz (knows Spy evs)) ⟶ P" (*>*)
section‹Event Traces \label{sec:events}›
text‹
system's behaviour is formalized as a set of traces of
emph{events}. The most important event, ‹Says A B X›, expresses
A\to B : X$, which is the attempt by~$A$ to send~$B$ the message~$X$.
trace is simply a list, constructed in reverse
~‹#›. Other event types include reception of messages (when
want to make it explicit) and an agent's storing a fact.
the protocol requires an agent to generate a new nonce. The
that a 20-byte random number has appeared before is effectively
. To formalize this important property, the set term‹used evs›
the set of all items mentioned in the trace~‹evs›.
function ‹used› has a straightforward
definition. Here is the case for ‹Says› event:
{thm [display,indent=5] used_Says [no_vars]}
function ‹knows› formalizes an agent's knowledge. Mostly we only
about the spy's knowledge, and term‹knows Spy evs› is the set of items
to the spy in the trace~‹evs›. Already in the empty trace,
spy starts with some secrets at his disposal, such as the private keys
compromised users. After each ‹Says› event, the spy learns the
that was sent:
{thm [display,indent=5] knows_Spy_Says [no_vars]}
of functions express other important
of messages derived from~‹evs›:
begin{itemize}
item term‹analz (knows Spy evs)› is everything that the spy could
by decryption
item term‹synth (analz (knows Spy evs))› is everything that the spy
generate
end{itemize} ›
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.