Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Doc/Tutorial/Protocol/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 31 kB image not shown  

Quelle  Message.thy

  Sprache: Isabelle
 

(*  Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
    Copyright   1996  University of Cambridge

Datatypes of agents and messages;
Inductive relations "parts", "analz" and "synth"
*)
(*<*)

sectionTheory of Agents and Messages for Security Protocols

theory Message imports "../Setup" begin

(*Needed occasionally with spy_analz_tac, e.g. in analz_insert_Key_newK*)
lemma [simp] : "A (B A) = B A"
by blast
(*>*)

sectionAgents and Messages

text 
  protocol specifications refer to a syntactic theory of messages.
 
 agent introduces the constant Server (a trusted central
 , needed for some protocols), an infinite population of
  agents, and the~Spy:
 


datatype agent = Server | Friend nat | Spy

text 
  are just natural numbers. Function invKey maps a public key to
  matching private key, and vice versa:
 


type_synonym key = nat
consts invKey :: "key ==> key"
(*<*)
consts all_symmetric :: bool        ― true if all keys are symmetric

specification (invKey)
  invKey [simp]: "invKey (invKey K) = K"
  invKey_symmetric: "all_symmetric invKey = id"
    by (rule exI [of _ id], auto)


textThe inverse of a symmetric key is itself; that of a public key
 is the private key and vice versa


definition symKeys :: "key set" where
  "symKeys == {K. invKey K = K}"
(*>*)

text 
 
 msg introduces the message forms, which include agent names, nonces,
 , compound messages, and encryptions.
 


datatype
     msg = Agent  agent
         | Nonce  nat
         | Key    key
         | MPair  msg msg
         | Crypt  key msg

text 
 noindent
  notation $\comp{X\sb 1,\ldots X\sb{n-1},X\sb n}$
 
 \isa{MPair}\,X\sb 1\,\ldots\allowbreak(\isa{MPair}\,X\sb{n-1}\,X\sb n)$.

  datatype constructors are injective, we have the theorem
 {thm [display,indent=0] msg.inject(5) [THEN iffD1, of K X K' X']}
  ciphertext can be decrypted using only one key and
  yield only one plaintext. In the real world, decryption with the
  key succeeds but yields garbage. Our model of encryption is
  if encryption adds some redundancy to the plaintext, such as a
 , so that garbage can be detected.
 


(*<*)
textConcrete 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 keysFor :: "msg set ==> key set" where
    ― Keys useful to decrypt elements of a message set
  "keysFor H == invKey ` {K. X. Crypt K X H}"


subsubsectionInductive 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"


textMonotonicity
lemma parts_mono: "G H ==> parts(G) parts(H)"
apply auto
apply (erule parts.induct) 
apply (blast dest: parts.Fst parts.Snd parts.Body)+
done


textEquations hold because constructors are injective.
lemma Friend_image_eq [simp]: "(Friend x Friend`A) = (xA)"
by auto

lemma Key_image_eq [simp]: "(Key x Key`A) = (xA)"
by auto

lemma Nonce_Key_image_eq [simp]: "(Nonce x Key`A)"
by auto


subsubsectionInverse of keys

lemma invKey_eq [simp]: "(invKey K = invKey K') = (K=K')"
apply safe
apply (drule_tac f = invKey in arg_cong, simp)
done


subsectionkeysFor operator

lemma keysFor_empty [simp]: "keysFor {} = {}"
by (unfold keysFor_def, blast)

lemma keysFor_Un [simp]: "keysFor (H H') = keysFor H keysFor H'"
by (unfold keysFor_def, blast)

lemma keysFor_UN [simp]: "keysFor (iA. H i) = (iA. keysFor (H i))"
by (unfold keysFor_def, blast)

textMonotonicity
lemma keysFor_mono: "G H ==> keysFor(G) keysFor(H)"
by (unfold keysFor_def, blast)

lemma keysFor_insert_Agent [simp]: "keysFor (insert (Agent A) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Nonce [simp]: "keysFor (insert (Nonce N) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Key [simp]: "keysFor (insert (Key K) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_MPair [simp]: "keysFor (insert {X,Y} H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Crypt [simp]: 
    "keysFor (insert (Crypt K X) H) = insert (invKey K) (keysFor H)"
by (unfold keysFor_def, auto)

lemma keysFor_image_Key [simp]: "keysFor (Key`E) = {}"
by (unfold keysFor_def, auto)

lemma Crypt_imp_invKey_keysFor: "Crypt K X H ==> invKey K keysFor H"
by (unfold keysFor_def, blast)


subsectionInductive 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!]
textNB 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_empty [simp]: "parts{} = {}"
apply safe
apply (erule parts.induct, blast+)
done

lemma parts_emptyE [elim!]: "X parts{} ==> P"
by simp

textWARNING: loops if H = {Y}, therefore must not be repeated!
lemma parts_singleton: "X parts H ==> YH. X parts {Y}"
by (erule parts.induct, fast+)


subsubsectionUnions

lemma parts_Un_subset1: "parts(G) parts(H) parts(G H)"
by (intro Un_least parts_mono Un_upper1 Un_upper2)

lemma parts_Un_subset2: "parts(G H) parts(G) parts(H)"
apply (rule subsetI)
apply (erule parts.induct, blast+)
done

lemma parts_Un [simp]: "parts(G H) = parts(G) parts(H)"
by (intro equalityI parts_Un_subset1 parts_Un_subset2)

lemma parts_insert: "parts (insert X H) = parts {X} parts H"
apply (subst insert_is_Un [of _ H])
apply (simp only: parts_Un)
done

textTWO inserts to avoid looping. This rewrite is better than nothing.
 Not suitable for Addsimps: its behaviour can be strange.

lemma parts_insert2:
     "parts (insert X (insert Y H)) = parts {X} parts {Y} parts H"
apply (simp add: Un_assoc)
apply (simp add: parts_insert [symmetric])
done

lemma parts_UN_subset1: "(xA. parts(H x)) parts(xA. H x)"
by (intro UN_least parts_mono UN_upper)

lemma parts_UN_subset2: "parts(xA. H x) (xA. parts(H x))"
apply (rule subsetI)
apply (erule parts.induct, blast+)
done

lemma parts_UN [simp]: "parts(xA. H x) = (xA. parts(H x))"
by (intro equalityI parts_UN_subset1 parts_UN_subset2)

textAdded to simplify arguments to parts, analz and synth.
 NOTE: the UN versions are no longer used!



textThis allows blast to simplify occurrences of
 termparts(GH) 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])

subsubsectionIdempotence 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 (iprover intro: subset_trans parts_increasing)  
apply (frule parts_mono, simp) 
done

lemma parts_trans: "[| X parts G; G parts H |] ==> X parts H"
by (drule parts_mono, blast)

textCut
lemma parts_cut:
     "[| Y parts (insert X G); X parts H |] ==> Y parts (G H)" 
by (blast intro: parts_trans) 


lemma parts_cut_eq [simp]: "X parts H ==> parts (insert X H) = parts H"
by (force dest!: parts_cut intro: parts_insertI)


subsubsectionRewrite rules for pulling out atomic messages

lemmas parts_insert_eq_I = equalityI [OF subsetI parts_insert_subset]


lemma parts_insert_Agent [simp]:
     "parts (insert (Agent agt) H) = insert (Agent agt) (parts H)"
apply (rule parts_insert_eq_I) 
apply (erule parts.induct, auto) 
done

lemma parts_insert_Nonce [simp]:
     "parts (insert (Nonce N) H) = insert (Nonce N) (parts H)"
apply (rule parts_insert_eq_I) 
apply (erule parts.induct, auto) 
done

lemma parts_insert_Key [simp]:
     "parts (insert (Key K) H) = insert (Key K) (parts H)"
apply (rule parts_insert_eq_I) 
apply (erule parts.induct, auto) 
done

lemma parts_insert_Crypt [simp]:
     "parts (insert (Crypt K X) H) = insert (Crypt K X) (parts (insert X H))"
apply (rule equalityI)
apply (rule subsetI)
apply (erule parts.induct, auto)
apply (blast intro: parts.Body)
done

lemma parts_insert_MPair [simp]:
     "parts (insert {X,Y} H) =
          insert {X,Y} (parts (insert X (insert Y H)))"
apply (rule equalityI)
apply (rule subsetI)
apply (erule parts.induct, auto)
apply (blast intro: parts.Fst parts.Snd)+
done

lemma parts_image_Key [simp]: "parts (Key`N) = Key`N"
apply auto
apply (erule parts.induct, auto)
done


textIn any message, there is an upper bound N on its greatest nonce.
lemma msg_Nonce_supply: "N. n. Nn Nonce n parts {msg}"
apply (induct_tac "msg")
apply (simp_all (no_asm_simp) add: exI parts_insert2)
 txtMPair case: blast works out the necessary sum itself!
 prefer 2 apply auto apply (blast elim!: add_leE)
txtNonce case
apply (rename_tac nat)
apply (rule_tac x = "N + Suc nat" in exI, auto) 
done
(*>*)

sectionModelling the Adversary

text 
  spy is part of the system and must be built into the model. He is
  malicious user who does not have to follow the protocol. He
  the network and uses any keys he knows to decrypt messages.
  he accumulates additional keys and nonces. These he can use to
  new messages, which he may send to anybody.

  functions enable us to formalize this behaviour: analz and
 synth. Each function maps a sets of messages to another set of
 . The set analz H formalizes what the adversary can learn
  the set of messages~$H$. The closure properties of this set are
  inductively.
 


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"
(*<*)
textMonotonicity; Lemma 1 of Lowe's paper
lemma analz_mono: "GH ==> analz(G) analz(H)"
apply auto
apply (erule analz.induct) 
apply (auto dest: analz.Fst analz.Snd) 
done

textMaking 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

lemmas analz_into_parts = analz_subset_parts [THEN subsetD]

lemmas not_parts_not_analz = analz_subset_parts [THEN contra_subsetD]


lemma parts_analz [simp]: "parts (analz H) = parts H"
apply (rule equalityI)
apply (rule analz_subset_parts [THEN parts_mono, THEN subset_trans], simp)
apply (blast intro: analz_increasing [THEN parts_mono, THEN subsetD])
done

lemma analz_parts [simp]: "analz (parts H) = parts H"
apply auto
apply (erule analz.induct, auto)
done

lemmas analz_insertI = subset_insertI [THEN analz_mono, THEN [2] rev_subsetD]

subsubsectionGeneral equational properties

lemma analz_empty [simp]: "analz{} = {}"
apply safe
apply (erule analz.induct, blast+)
done

textConverse 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])

subsubsectionRewrite rules for pulling out atomic messages

lemmas analz_insert_eq_I = equalityI [OF subsetI analz_insert]

lemma analz_insert_Agent [simp]:
     "analz (insert (Agent agt) H) = insert (Agent agt) (analz H)"
apply (rule analz_insert_eq_I) 
apply (erule analz.induct, auto) 
done

lemma analz_insert_Nonce [simp]:
     "analz (insert (Nonce N) H) = insert (Nonce N) (analz H)"
apply (rule analz_insert_eq_I) 
apply (erule analz.induct, auto) 
done

textCan only pull out Keys if they are not needed to decrypt the rest
lemma analz_insert_Key [simp]: 
    "K keysFor (analz H) ==>
          analz (insert (Key K) H) = insert (Key K) (analz H)"
apply (unfold keysFor_def)
apply (rule analz_insert_eq_I) 
apply (erule analz.induct, auto) 
done

lemma analz_insert_MPair [simp]:
     "analz (insert {X,Y} H) =
          insert {X,Y} (analz (insert X (insert Y H)))"
apply (rule equalityI)
apply (rule subsetI)
apply (erule analz.induct, auto)
apply (erule analz.induct)
apply (blast intro: analz.Fst analz.Snd)+
done

textCan 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)

textCase 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 termanalz (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)


textThis 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_image_Key [simp]: "analz (Key`N) = Key`N"
apply auto
apply (erule analz.induct, auto)
done


subsubsectionIdempotence and transitivity

lemma analz_analzD [dest!]: "X analz (analz H) ==> X analz H"
by (erule analz.induct, blast+)

lemma analz_idem [simp]: "analz (analz H) = analz H"
by blast

lemma analz_subset_iff [simp]: "(analz G analz H) = (G analz H)"
apply (rule iffI)
apply (iprover intro: subset_trans analz_increasing)  
apply (frule analz_mono, simp) 
done

lemma analz_trans: "[| X analz G; G analz H |] ==> X analz H"
by (drule analz_mono, blast)

textCut; Lemma 2 of Lowe
lemma analz_cut: "[| Y analz (insert X H); X analz H |] ==> Y analz H"
by (erule analz_trans, blast)

(*Cut can be proved easily by induction on
   "Y \<in> analz (insert X H) \<Longrightarrow> X \<in> analz H \<longrightarrow> Y \<in> analz H"
*)


textThis 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)


textA congruence rule for "analz"

lemma analz_subset_cong:
     "[| analz G analz G'; analz H analz H' |]
      ==> analz (G H) analz (G' H')"
apply simp
apply (iprover intro: conjI subset_trans analz_mono Un_upper1 Un_upper2) 
done

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)

textIf 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

textThese two are obsolete (with a single Spy) but cost little to prove...
lemma analz_UN_analz_lemma:
     "X analz (iA. analz (H i)) ==> X analz (iA. H i)"
apply (erule analz.induct)
apply (blast intro: analz_mono [THEN [2] rev_subsetD])+
done

lemma analz_UN_analz [simp]: "analz (iA. analz (H i)) = analz (iA. H i)"
by (blast intro: analz_UN_analz_lemma analz_mono [THEN [2] rev_subsetD])
(*>*)
text 
  the Decrypt rule: the spy can decrypt a
  encrypted with key~$K$ if he has the matching key,~$K^{-1}$.
  proved by rule induction include the following:
 {named_thms [display,indent=0] analz_mono [no_vars] (analz_mono) analz_idem [no_vars] (analz_idem)}

  set of fake messages that an intruder could invent
  from~H is synth(analz H), where synth H
  what the adversary can build from the set of messages~$H$.
 


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"
  | 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"
(*<*)
lemma synth_mono: "GH ==> synth(G) synth(H)"
  by (auto, erule synth.induct, auto)  

inductive_cases Key_synth   [elim!]: "Key K synth H"
inductive_cases MPair_synth [elim!]: "{X,Y} synth H"
inductive_cases Crypt_synth [elim!]: "Crypt K X synth H"

lemma analz_synth_Un [simp]: "analz (synth G H) = analz (G H) synth G"
apply (rule equalityI)
apply (rule subsetI)
apply (erule analz.induct)
prefer 5 apply (blast intro: analz_mono [THEN [2] rev_subsetD])
apply (blast intro: analz.Fst analz.Snd analz.Decrypt)+
done

lemma analz_synth [simp]: "analz (synth H) = analz H synth H"
apply (cut_tac H = "{}" in analz_synth_Un)
apply (simp (no_asm_use))
done
(*>*)
text 
  set includes all agent names. Nonces and keys are assumed to be
 , so none are included beyond those already in~$H$. Two
  of termsynth H can be combined, and an element can be encrypted
  a key present in~$H$.

  analz, this set operator is monotone and idempotent. It also
  an interesting equation involving analz:
 {named_thms [display,indent=0] analz_synth [no_vars] (analz_synth)}
  inversion plays a major role in reasoning about synth, through
  such as this one:
 


inductive_cases Nonce_synth [elim!]: "Nonce n synth H"

text 
 noindent
  resulting elimination rule replaces every assumption of the form
 termNonce n synth H by termNonce n H,
  that a nonce cannot be guessed.

  third operator, parts, is useful for stating correctness
 . The set
 termparts H consists of the components of elements of~$H$. This set
 ~H and is closed under the projections from a compound
  to its immediate parts.
  definition resembles that of analz except in the rule
  to the constructor Crypt:
 {thm [display,indent=5] parts.Body [no_vars]}
  body of an encrypted message is always regarded as part of it. We can
  parts to express general well-formedness properties of a protocol,
  example, that an uncompromised agent's private key will never be
  as a component of any message.
 

(*<*)
lemma synth_increasing: "H synth(H)"
by blast

subsubsectionUnions

textConverse 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 (blast intro: synth_mono [THEN [2] rev_subsetD])

subsubsectionIdempotence and transitivity

lemma synth_synthD [dest!]: "X synth (synth H) ==> X synth H"
by (erule synth.induct, blast+)

lemma synth_idem: "synth (synth H) = synth H"
by blast

lemma synth_subset_iff [simp]: "(synth G synth H) = (G synth H)"
apply (rule iffI)
apply (iprover intro: subset_trans synth_increasing)  
apply (frule synth_mono, simp add: synth_idem) 
done

lemma synth_trans: "[| X synth G; G synth H |] ==> X synth H"
by (drule synth_mono, blast)

textCut; Lemma 2 of Lowe
lemma synth_cut: "[| Y synth (insert X H); X synth H |] ==> Y synth H"
by (erule synth_trans, blast)

lemma Agent_synth [simp]: "Agent A synth H"
by blast

lemma Nonce_synth_eq [simp]: "(Nonce N synth H) = (Nonce N H)"
by blast

lemma Key_synth_eq [simp]: "(Key K synth H) = (Key K H)"
by blast

lemma Crypt_synth_eq [simp]:
     "Key K H ==> (Crypt K X synth H) = (Crypt K X H)"
by blast


lemma keysFor_synth [simp]: 
    "keysFor (synth H) = keysFor H invKey`{K. Key K H}"
by (unfold keysFor_def, blast)


subsubsectionCombinations of parts, analz and synth

lemma parts_synth [simp]: "parts (synth H) = parts H synth H"
apply (rule equalityI)
apply (rule subsetI)
apply (erule parts.induct)
apply (blast intro: synth_increasing [THEN parts_mono, THEN subsetD] 
                    parts.Fst parts.Snd parts.Body)+
done

lemma analz_analz_Un [simp]: "analz (analz G H) = analz (G H)"
apply (intro equalityI analz_subset_cong)+
apply simp_all
done


subsubsectionFor reasoning about the Fake rule in traces

lemma parts_insert_subset_Un: "X G ==> parts(insert X H) parts G parts H"
by (rule subset_trans [OF parts_mono parts_Un_subset2], blast)

textMore specifically for Fake. Very occasionally we could do with a version
 of the form termparts{X} synth (analz H) parts H

lemma Fake_parts_insert:
     "X synth (analz H) ==>
      parts (insert X H) synth (analz H) parts H"
apply (drule parts_insert_subset_Un)
apply (simp (no_asm_use))
apply blast
done

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])

texttermH is sometimes termKey ` KK spies evs, so can't put
 termG=H.

lemma Fake_analz_insert:
     "X synth (analz G) ==>
      analz (insert X H) synth (analz G) analz (G H)"
apply (rule subsetI)
apply (subgoal_tac "x analz (synth (analz G) H) ")
prefer 2 apply (blast intro: analz_mono [THEN [2] rev_subsetD] analz_mono [THEN synth_mono, THEN [2] rev_subsetD])
apply (simp (no_asm_use))
apply blast
done

lemma analz_conj_parts [simp]:
     "(X analz H & X parts H) = (X analz H)"
by (blast intro: analz_subset_parts [THEN subsetD])

lemma analz_disj_parts [simp]:
     "(X analz H | X parts H) = (X parts H)"
by (blast intro: analz_subset_parts [THEN subsetD])

textWithout this equation, other rules for synth and analz would yield
 redundant cases

lemma MPair_synth_analz [iff]:
     "({X,Y} synth (analz H)) =
      (X synth (analz H) & Y synth (analz H))"
by blast

lemma Crypt_synth_analz:
     "[| Key K analz H; Key (invKey K) analz H |]
       ==> (Crypt K X synth (analz H)) = (X synth (analz H))"
by blast


textWe do NOT want Crypt... messages broken up in protocols!!
declare parts.Body [rule del]


textRewrites to push in Key and Crypt messages, so that other messages can
 be pulled out using the analz_insert rules


lemmas pushKeys =
  insert_commute [of "Key K" "Agent C"]
  insert_commute [of "Key K" "Nonce N"]
  insert_commute [of "Key K" "MPair X Y"]
  insert_commute [of "Key K" "Crypt X K'"]
  for K C N X Y K'

lemmas pushCrypts =
  insert_commute [of "Crypt X K" "Agent C"]
  insert_commute [of "Crypt X K" "Agent C"]
  insert_commute [of "Crypt X K" "Nonce N"]
  insert_commute [of "Crypt X K" "MPair X' Y"]
  for X K C N X' Y

textCannot be added with [simp] -- messages should not always be
 re-ordered.

lemmas pushes = pushKeys pushCrypts


subsectionTactics useful for many protocol proofs
ML

  invKey = @{thm invKey};
  keysFor_def = @{thm keysFor_def};
  symKeys_def = @{thm symKeys_def};
  parts_mono = @{thm parts_mono};
  analz_mono = @{thm analz_mono};
  synth_mono = @{thm synth_mono};
  analz_increasing = @{thm analz_increasing};

  analz_insertI = @{thm analz_insertI};
  analz_subset_parts = @{thm analz_subset_parts};
  Fake_parts_insert = @{thm Fake_parts_insert};
  Fake_analz_insert = @{thm Fake_analz_insert};
  pushes = @{thms pushes};


 
 but this application is no longer necessary if analz_insert_eq is used.
 Abstraction over i is ESSENTIAL: it delays the dereferencing of claset
  DEPENDS UPON "X" REFERRING TO THE FRADULENT MESSAGE *)


(*Apply rules to break down assumptions of the form
  Y \<in> parts(insert X H)  and  Y \<in> analz(insert X H)
*)

fun impOfSubs th = th RSN (2, @{thm rev_subsetD})

fun Fake_insert_tac ctxt =
    dresolve_tac ctxt [impOfSubs Fake_analz_insert,
                  impOfSubs Fake_parts_insert] THEN'
    eresolve_tac ctxt [asm_rl, @{thm synth.Inj}];

fun Fake_insert_simp_tac ctxt i = 
  REPEAT (Fake_insert_tac ctxt i) THEN asm_full_simp_tac ctxt i;

fun atomic_spy_analz_tac ctxt =
  SELECT_GOAL
   (Fake_insert_simp_tac ctxt 1 THEN
    IF_UNSOLVED (Blast.depth_tac (ctxt addIs [analz_insertI, impOfSubs analz_subset_parts]4 1));

fun spy_analz_tac ctxt i =
  DETERM
   (SELECT_GOAL
     (EVERY 
      [  (*push in occurrences of X...*)
       (REPEAT o CHANGED)
         (Rule_Insts.res_inst_tac ctxt [((("x"1), Position.none), "X")] []
           (@{thm insert_commute} RS ssubst) 1),
       (*...allowing further simplifications*)
       simp_tac ctxt 1,
       REPEAT (FIRSTGOAL (resolve_tac ctxt [allI,impI,notI,conjI,iffI])),
       DEPTH_SOLVE (atomic_spy_analz_tac ctxt 1)]) i);


textBy default only o_apply is built-in.  But in the presence of
eta-expansion this means that some terms displayed as termf o g will be
rewritten, and others will not!

declare o_def [simp]


lemma Crypt_notin_image_Key [simp]: "Crypt K X Key ` A"
by auto

lemma synth_analz_mono: "GH ==> synth (analz(G)) synth (analz(H))"
by (iprover intro: synth_mono analz_mono) 

lemma Fake_analz_eq [simp]:
     "X synth(analz H) ==> synth (analz (insert X H)) = synth (analz H)"
apply (drule Fake_analz_insert[of _ _ "H"])
apply (simp add: synth_increasing[THEN Un_absorb2])
apply (drule synth_mono)
apply (simp add: synth_idem)
apply (rule equalityI)
apply (simp add: )
apply (rule synth_analz_mono, blast)   
done

textTwo generalizations of analz_insert_eq\ lemma gen_analz_insert_eq [rule_format]:
     "X analz H ==> G. H G analz (insert X G) = analz G"
by (blast intro: analz_cut analz_insertI analz_mono [THEN [2] rev_subsetD])

lemma synth_analz_insert_eq [rule_format]:
     "X synth (analz H)

      ==> G. H G (Key K analz (insert X G)) = (Key K analz G)"
apply (erule synth.induct) 
apply (simp_all add: gen_analz_insert_eq subset_trans [OF _ subset_insertI]) 
done

lemma Fake_parts_sing:
     "X synth (analz H) ==> parts{X} synth (analz H) parts H"
apply (rule subset_trans) 
 apply (erule_tac [2] Fake_parts_insert)
apply (rule parts_mono, blast)
done

lemmas Fake_parts_sing_imp_Un = Fake_parts_sing [THEN [2] rev_subsetD]

method_setup spy_analz = 
 Scan.succeed (SIMPLE_METHOD' o spy_analz_tac)

    "for proving the Fake case when analz is involved"

method_setup atomic_spy_analz = 
 Scan.succeed (SIMPLE_METHOD' o atomic_spy_analz_tac)

    "for debugging spy_analz"

method_setup Fake_insert_simp = 
 Scan.succeed (SIMPLE_METHOD' o Fake_insert_simp_tac)

    "for debugging spy_analz"


end
(*>*)

Messung V0.5 in Prozent
C=87 H=98 G=92

¤ Dauer der Verarbeitung: 0.16 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.