Theory Authentication

(*  Title:       The Relational Method with Message Anonymity for the Verification of Cryptographic Protocols
    Author:      Pasquale Noce
                 Software Engineer at HID Global, Italy
                 pasquale dot noce dot lavoro at gmail dot com
                 pasquale dot noce at hidglobal dot com
*)

section "Confidentiality and authenticity properties"

theory Authentication
  imports Definitions
begin

text ‹
\label{Authentication}
›


proposition rtrancl_start [rule_format]:
 "(x, y) ∈ r* ⟹ P y ⟶ ¬ P x ⟶
    (∃u v. (x, u) ∈ r* ∧ (u, v) ∈ r ∧ (v, y) ∈ r* ∧ ¬ P u ∧ P v)"
  (is "_ ⟹ _ ⟶ _ ⟶ (∃u v. ?Q x y u v)")
proof (erule rtrancl_induct, simp, (rule impI)+)
  fix y z
  assume
    A: "(x, y) ∈ r*" and
    B: "(y, z) ∈ r" and
    C: "P z"
  assume "P y ⟶ ¬ P x ⟶(∃u v. ?Q x y u v)" and "¬ P x"
  hence D: "P y ⟶ (∃u v. ?Q x y u v)" by simp
  show "∃u v. ?Q x z u v"
  proof (cases "P y")
    case True
    with D obtain u v where "?Q x y u v" by blast
    moreover from this and B have "(v, z) ∈ r*" by auto
    ultimately show ?thesis by blast
  next
    case False
    with A and B and C have "?Q x z y z" by simp
    thus ?thesis by blast
  qed
qed


proposition state_subset:
 "s ⊨ s' ⟹ s ⊆ s'"
by (erule rtrancl_induct, auto simp add: rel_def image_def)

proposition spied_subset:
 "s ⊨ s' ⟹ spied s ⊆ spied s'"
by (rule Image_mono, erule state_subset, simp)

proposition used_subset:
 "s ⊨ s' ⟹ used s ⊆ used s'"
by (rule Range_mono, rule state_subset)

proposition asset_ii_init:
 "⟦s0 ⊨ s; (Asset n, ⦃Num 2, PubKey A⦄) ∈ s⟧ ⟹
    PriKey A ∉ spied s0"
by (drule rtrancl_start, assumption, simp add: image_def, (erule exE)+,
 erule conjE, rule notI, drule spied_subset, drule subsetD, assumption,
 auto simp add: rel_def)

proposition auth_prikey_used:
 "s0 ⊨ s ⟹ Auth_PriKey n ∈ used s"
by (drule used_subset, erule subsetD, simp add: Range_iff image_def, blast)

proposition asset_i_used:
 "s0 ⊨ s ⟹
    (Asset n, Crypt (Auth_ShaKey n) (PriKey A)) ∈ s ⟶
  PriKey A ∈ used s"
by (erule rtrancl_induct, auto simp add: rel_def image_def)

proposition owner_ii_used:
 "s0 ⊨ s ⟹
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ⟶
  PriKey A ∈ used s"
by (erule rtrancl_induct, auto simp add: rel_def image_def)

proposition asset_ii_used:
 "s0 ⊨ s ⟹
    (Asset n, ⦃Num 2, PubKey A⦄) ∈ s ⟶
  PriKey A ∈ used s"
by (erule rtrancl_induct, auto simp add: rel_def image_def)

proposition owner_iii_used:
 "s0 ⊨ s ⟹
    (Owner n, ⦃Num 3, PubKey A⦄) ∈ s ⟶
  PriKey A ∈ used s"
by (erule rtrancl_induct, auto simp add: rel_def image_def)

proposition asset_iii_used:
 "s0 ⊨ s ⟹
    (Asset n, ⦃Num 4, PubKey A⦄) ∈ s ⟶
  PriKey A ∈ used s"
by (erule rtrancl_induct, auto simp add: rel_def image_def)

proposition asset_i_unique [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, Crypt (Auth_ShaKey m) (PriKey A)) ∈ s ⟶
    (Asset n, Crypt (Auth_ShaKey n) (PriKey A)) ∈ s ⟶
  m = n"
by (erule rtrancl_induct, simp add: image_def, frule asset_i_used [of _ m A],
 drule asset_i_used [of _ n A], auto simp add: rel_def)

proposition owner_ii_unique [rule_format]:
 "s0 ⊨ s ⟹
    (Owner m, ⦃Num 1, PubKey A⦄) ∈ s ⟶
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ⟶
  m = n"
by (erule rtrancl_induct, simp add: image_def, frule owner_ii_used [of _ m A],
 drule owner_ii_used [of _ n A], auto simp add: rel_def)

proposition asset_ii_unique [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 2, PubKey A⦄) ∈ s ⟶
    (Asset n, ⦃Num 2, PubKey A⦄) ∈ s ⟶
  m = n"
by (erule rtrancl_induct, simp add: image_def, frule asset_ii_used [of _ m A],
 drule asset_ii_used [of _ n A], auto simp add: rel_def)

proposition auth_prikey_asset_i [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, Crypt (Auth_ShaKey m) (Auth_PriKey n)) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, drule auth_prikey_used [of _ n],
 auto simp add: rel_def)

proposition auth_pubkey_owner_ii [rule_format]:
 "s0 ⊨ s ⟹
    (Owner m, ⦃Num 1, Auth_PubKey n⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, drule auth_prikey_used [of _ n],
 auto simp add: rel_def)

proposition auth_pubkey_owner_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Owner m, ⦃Num 3, Auth_PubKey n⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, drule auth_prikey_used [of _ n],
 auto simp add: rel_def)

proposition auth_pubkey_asset_ii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 2, Auth_PubKey n⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, drule auth_prikey_used [of _ n],
 auto simp add: rel_def)

proposition auth_pubkey_asset_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 4, Auth_PubKey n⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, drule auth_prikey_used [of _ n],
 auto simp add: rel_def)

proposition asset_i_owner_ii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, Crypt (Auth_ShaKey m) (PriKey A)) ∈ s ⟶
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_i_used [of _ m A],
 drule owner_ii_used [of _ n A], auto simp add: rel_def)

proposition asset_i_owner_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, Crypt (Auth_ShaKey m) (PriKey A)) ∈ s ⟶
    (Owner n, ⦃Num 3, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_i_used [of _ m A],
 drule owner_iii_used [of _ n A], auto simp add: rel_def)

proposition asset_i_asset_ii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, Crypt (Auth_ShaKey m) (PriKey A)) ∈ s ⟶
    (Asset n, ⦃Num 2, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_i_used [of _ m A],
 drule asset_ii_used [of _ n A], auto simp add: rel_def)

proposition asset_i_asset_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, Crypt (Auth_ShaKey m) (PriKey A)) ∈ s ⟶
    (Asset n, ⦃Num 4, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_i_used [of _ m A],
 drule asset_iii_used [of _ n A], auto simp add: rel_def)

proposition asset_ii_owner_ii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 2, PubKey A⦄) ∈ s ⟶
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_ii_used [of _ m A],
 drule owner_ii_used [of _ n A], auto simp add: rel_def)

proposition asset_ii_owner_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 2, PubKey A⦄) ∈ s ⟶
    (Owner n, ⦃Num 3, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_ii_used [of _ m A],
 drule owner_iii_used [of _ n A], auto simp add: rel_def)

proposition asset_ii_asset_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 2, PubKey A⦄) ∈ s ⟶
    (Asset n, ⦃Num 4, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_ii_used [of _ m A],
 drule asset_iii_used [of _ n A], auto simp add: rel_def)

proposition asset_iii_owner_iii [rule_format]:
 "s0 ⊨ s ⟹
    (Asset m, ⦃Num 4, PubKey A⦄) ∈ s ⟶
    (Owner n, ⦃Num 3, PubKey A⦄) ∈ s ⟶
  False"
by (erule rtrancl_induct, simp add: image_def, frule asset_iii_used [of _ m A],
 drule owner_iii_used [of _ n A], auto simp add: rel_def)

proposition asset_iv_state [rule_format]:
 "s0 ⊨ s ⟹
    (Asset n, Token n (Auth_PriK n) B C SK) ∈ s ⟶
  (∃A D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    (Asset n, ⦃Num 2, PubKey B⦄) ∈ s ∧ (Asset n, ⦃Num 4, PubKey D⦄) ∈ s ∧
    Crypt (SesK SK) (PubKey D) ∈ used s ∧ (Asset n, PubKey B) ∈ s)"
by (erule rtrancl_induct, auto simp add: rel_def)

proposition owner_v_state [rule_format]:
 "s0 ⊨ s ⟹
    (Owner n, Crypt (SesK SK) (Pwd n)) ∈ s ⟶
  (Owner n, SesKey SK) ∈ s ∧
  (∃A B C. Token n A B C SK ∈ used s ∧ B ∈ fst (snd SK))"
by (erule rtrancl_induct, auto simp add: rel_def, blast)

proposition asset_v_state [rule_format]:
 "s0 ⊨ s ⟹
    (Asset n, Crypt (SesK SK) (Num 0)) ∈ s ⟶
  (Asset n, SesKey SK) ∈ s ∧ Crypt (SesK SK) (Pwd n) ∈ used s"
by (erule rtrancl_induct, simp_all add: rel_def image_def,
 ((erule disjE)?, (erule exE)+, simp add: Range_Un_eq)+)

lemma owner_seskey_nonce_1:
 "⟦s ⊢ s';
    (Owner n, SesKey SK) ∈ s ⟶
      (∃S. fst SK = Some S ∧ Crypt (Auth_ShaKey n) (PriKey S) ∈ used s) ∨
      fst SK = None;
    (Owner n, SesKey SK) ∈ s'⟧ ⟹
  (∃S. fst SK = Some S ∧ Crypt (Auth_ShaKey n) (PriKey S) ∈ used s') ∨
  fst SK = None"
by (simp add: rel_def, (erule disjE, (erule exE)+, simp+)+,
 split if_split_asm, auto)

proposition owner_seskey_nonce [rule_format]:
 "s0 ⊨ s ⟹
    (Owner n, SesKey SK) ∈ s ⟶
  (∃S. fst SK = Some S ∧ Crypt (Auth_ShaKey n) (PriKey S) ∈ used s) ∨
  fst SK = None"
by (erule rtrancl_induct, simp add: image_def, rule impI, rule owner_seskey_nonce_1)

proposition owner_seskey_other [rule_format]:
 "s0 ⊨ s ⟹
    (Owner n, SesKey SK) ∈ s ⟶
  (∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ∧
    (Owner n, ⦃Num 3, PubKey C⦄) ∈ s ∧
    (Owner n, Crypt (SesK SK) (PubKey D)) ∈ s)"
by (erule rtrancl_induct, auto simp add: rel_def, blast+)

proposition asset_seskey_nonce [rule_format]:
 "s0 ⊨ s ⟹
    (Asset n, SesKey SK) ∈ s ⟶
  (∃S. fst SK = Some S ∧ (Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s)"
by (erule rtrancl_induct, auto simp add: rel_def)

proposition asset_seskey_other [rule_format]:
 "s0 ⊨ s ⟹
    (Asset n, SesKey SK) ∈ s ⟶
  (∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    (Asset n, ⦃Num 2, PubKey B⦄) ∈ s ∧ (Asset n, ⦃Num 4, PubKey D⦄) ∈ s ∧
    (Asset n, Token n (Auth_PriK n) B C SK) ∈ s)"
by (erule rtrancl_induct, auto simp add: rel_def, blast)


declare Range_Un_eq [simp]

proposition used_prod [simp]:
 "A ≠ {} ⟹ used (A × H) = H"
by (simp add: Range_snd)

proposition parts_idem [simp]:
 "parts (parts H) = parts H"
by (rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_mono:
 "H ⊆ H' ⟹ parts H ⊆ parts H'"
by (rule subsetI, erule parts.induct, auto)

proposition parts_msg_mono:
 "X ∈ H ⟹ parts_msg X ⊆ parts H"
by (subgoal_tac "{X} ⊆ H", subst parts_msg_def, erule parts_mono, simp)

lemma parts_union_1:
 "parts (H ∪ H') ⊆ parts H ∪ parts H'"
by (rule subsetI, erule parts.induct, auto)

lemma parts_union_2:
 "parts H ∪ parts H' ⊆ parts (H ∪ H')"
by (rule subsetI, erule UnE, erule_tac [!] parts.induct, auto)

proposition parts_union [simp]:
 "parts (H ∪ H') = parts H ∪ parts H'"
by (rule equalityI, rule parts_union_1, rule parts_union_2)

proposition parts_insert:
 "parts (insert X H) = parts_msg X ∪ parts H"
by (simp only: insert_def parts_union, subst parts_msg_def, simp)

proposition parts_msg_num [simp]:
 "parts_msg (Num n) = {Num n}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_msg_pwd [simp]:
 "parts_msg (Pwd n) = {Pwd n}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_msg_key [simp]:
 "parts_msg (Key K) = {Key K}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_msg_mult [simp]:
 "parts_msg (A ⊗ B) = {A ⊗ B}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_msg_hash [simp]:
 "parts_msg (Hash X) = {Hash X}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

lemma parts_crypt_1:
 "parts {Crypt K X} ⊆ insert (Crypt K X) (parts {X})"
by (rule subsetI, erule parts.induct, auto)

lemma parts_crypt_2:
 "insert (Crypt K X) (parts {X}) ⊆ parts {Crypt K X}"
by (rule subsetI, simp, erule disjE, blast, erule parts.induct, auto)

proposition parts_msg_crypt [simp]:
 "parts_msg (Crypt K X) = insert (Crypt K X) (parts_msg X)"
by (simp add: parts_msg_def, rule equalityI, rule parts_crypt_1, rule parts_crypt_2)

lemma parts_mpair_1:
 "parts {⦃X, Y⦄} ⊆ insert ⦃X, Y⦄ (parts {X} ∪ parts {Y})"
by (rule subsetI, erule parts.induct, auto)

lemma parts_mpair_2:
 "insert ⦃X, Y⦄ (parts {X} ∪ parts {Y}) ⊆ parts {⦃X, Y⦄}"
by (rule subsetI, simp, erule disjE, blast, erule disjE, erule_tac [!] parts.induct,
 auto)

proposition parts_msg_mpair [simp]:
 "parts_msg ⦃X, Y⦄ = insert ⦃X, Y⦄ (parts_msg X ∪ parts_msg Y)"
by (simp add: parts_msg_def, rule equalityI, rule parts_mpair_1, rule parts_mpair_2)

proposition parts_msg_idinfo [simp]:
 "parts_msg ⟨n, X⟩ = {⟨n, X⟩}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_msg_trace [simp]:
 "parts_msg (Log X) = {Log X}"
by (subst parts_msg_def, rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_idinfo [simp]:
 "parts (IDInfo n ` H) = IDInfo n ` H"
by (rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_trace [simp]:
 "parts (Log ` H) = Log ` H"
by (rule equalityI, rule subsetI, erule parts.induct, auto)

proposition parts_dec:
 "⟦s' = insert (Spy, X) s ∧ (Spy, Crypt K X) ∈ s ∧ (Spy, Key (InvK K)) ∈ s;
    Y ∈ parts_msg X⟧ ⟹
  Y ∈ parts (used s)"
by (subgoal_tac "X ∈ parts (used s)", drule parts_msg_mono [of X], auto)

proposition parts_enc:
 "⟦s' = insert (Spy, Crypt K X) s ∧ (Spy, X) ∈ s ∧ (Spy, Key K) ∈ s;
    Y ∈ parts_msg X⟧ ⟹
  Y ∈ parts (used s)"
by (subgoal_tac "X ∈ parts (used s)", drule parts_msg_mono [of X], auto)

proposition parts_sep:
 "⟦s' = insert (Spy, X) (insert (Spy, Y) s) ∧ (Spy, ⦃X, Y⦄) ∈ s;
    Z ∈ parts_msg X ∨ Z ∈ parts_msg Y⟧ ⟹
  Z ∈ parts (used s)"
by (erule disjE, subgoal_tac "X ∈ parts (used s)", drule parts_msg_mono [of X],
 subgoal_tac [3] "Y ∈ parts (used s)", drule_tac [3] parts_msg_mono [of Y], auto)

proposition parts_con:
 "⟦s' = insert (Spy, ⦃X, Y⦄) s ∧ (Spy, X) ∈ s ∧ (Spy, Y) ∈ s;
    Z ∈ parts_msg X ∨ Z ∈ parts_msg Y⟧ ⟹
  Z ∈ parts (used s)"
by (erule disjE, subgoal_tac "X ∈ parts (used s)", drule parts_msg_mono [of X],
 subgoal_tac [3] "Y ∈ parts (used s)", drule_tac [3] parts_msg_mono [of Y], auto)

lemma parts_init_1:
 "parts (used s0) ⊆ used s0 ∪ range (Hash ∘ Agent) ∪
    range (Hash ∘ Auth_PubKey) ∪
    range (λn. ⦃Hash (Agent n), Hash (Auth_PubKey n)⦄)"
by (rule subsetI, erule parts.induct, (clarify | simp add: Range_iff image_def)+)

lemma parts_init_2:
 "used s0 ∪ range (Hash ∘ Agent) ∪ range (Hash ∘ Auth_PubKey) ∪
    range (λn. ⦃Hash (Agent n), Hash (Auth_PubKey n)⦄) ⊆ parts (used s0)"
by (rule subsetI, auto simp add: parts_insert)

proposition parts_init:
 "parts (used s0) = used s0 ∪ range (Hash ∘ Agent) ∪
    range (Hash ∘ Auth_PubKey) ∪
    range (λn. ⦃Hash (Agent n), Hash (Auth_PubKey n)⦄)"
by (rule equalityI, rule parts_init_1, rule parts_init_2)


proposition parts_crypt_prikey_start:
 "⟦s ⊢ s'; Crypt K (PriKey A) ∈ parts (used s');
    Crypt K (PriKey A) ∉ parts (used s)⟧ ⟹
  (∃n. K = Auth_ShaKey n ∧
    (Asset n, Crypt (Auth_ShaKey n) (PriKey A)) ∈ s') ∨
  {PriKey A, Key K} ⊆ spied s'"
by (simp add: rel_def, erule disjE, (erule exE)+, simp add: parts_insert, blast,
 (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | erule disjE, simp, drule parts_enc |
 drule parts_sep | drule parts_con), simp+)?)+)

proposition parts_crypt_prikey:
 "⟦s0 ⊨ s; Crypt K (PriKey A) ∈ parts (used s)⟧ ⟹
    (∃n. K = Auth_ShaKey n ∧
      (Asset n, Crypt (Auth_ShaKey n) (PriKey A)) ∈ s) ∨
    {PriKey A, Key K} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_prikey_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_crypt_pubkey_start:
 "⟦s ⊢ s'; Crypt (SesK SK) (PubKey C) ∈ parts (used s');
    Crypt (SesK SK) (PubKey C) ∉ parts (used s)⟧ ⟹
  C ∈ snd (snd SK) ∧ ((∃n. (Owner n, SesKey SK) ∈ s') ∨
    (∃n B. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s')) ∨
  SesKey SK ∈ spied s'"
by (simp add: rel_def, (erule disjE, (erule exE)+, simp add: parts_insert image_iff)+,
 blast, erule disjE, (erule exE)+, simp add: parts_insert image_iff, blast,
 (((erule disjE)?, ((erule exE)+)?, simp add: parts_insert image_iff)+,
 ((drule parts_dec | drule parts_enc | drule parts_sep | drule parts_con), simp+)?)+)

proposition parts_crypt_pubkey:
 "⟦s0 ⊨ s; Crypt (SesK SK) (PubKey C) ∈ parts (used s)⟧ ⟹
    C ∈ snd (snd SK) ∧ ((∃n. (Owner n, SesKey SK) ∈ s) ∨
      (∃n B. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s)) ∨
    SesKey SK ∈ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_pubkey_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_crypt_key_start:
 "⟦s ⊢ s'; Crypt K (Key K') ∈ parts (used s');
    Crypt K (Key K') ∉ parts (used s); K' ∉ range PriK ∪ range PubK⟧ ⟹
  {Key K', Key K} ⊆ spied s'"
by (simp add: rel_def, (((erule disjE)?, ((erule exE)+)?, simp add: parts_insert
 image_iff)+, ((drule parts_dec | drule parts_enc | drule parts_sep | drule parts_con),
 simp+)?)+)

proposition parts_crypt_key:
 "⟦s0 ⊨ s; Crypt K (Key K') ∈ parts (used s);
    K' ∉ range PriK ∪ range PubK⟧ ⟹
  {Key K', Key K} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_key_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_crypt_sign_start:
 "⟦s ⊢ s'; Crypt (SesK SK) (Sign n A) ∈ parts (used s');
    Crypt (SesK SK) (Sign n A) ∉ parts (used s)⟧ ⟹
  (Asset n, SesKey SK) ∈ s' ∨ SesKey SK ∈ spied s'"
by (simp add: rel_def, (((erule disjE)?, ((erule exE)+)?, simp add: parts_insert
 image_iff)+, ((drule parts_dec | drule parts_enc | drule parts_sep | drule parts_con),
 simp+)?)+)

proposition parts_crypt_sign:
 "⟦s0 ⊨ s; Crypt (SesK SK) (Sign n A) ∈ parts (used s)⟧ ⟹
    (Asset n, SesKey SK) ∈ s ∨ SesKey SK ∈ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_sign_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_crypt_pwd_start:
 "⟦s ⊢ s'; Crypt K (Pwd n) ∈ parts (used s');
    Crypt K (Pwd n) ∉ parts (used s)⟧ ⟹
  (∃SK. K = SesK SK ∧ (Owner n, Crypt (SesK SK) (Pwd n)) ∈ s') ∨
  {Pwd n, Key K} ⊆ spied s'"
by (simp add: rel_def, (((erule disjE)?, ((erule exE)+)?, simp add: parts_insert
 image_iff)+, ((drule parts_dec | drule parts_enc | drule parts_sep | drule parts_con),
 simp+)?)+)

proposition parts_crypt_pwd:
 "⟦s0 ⊨ s; Crypt K (Pwd n) ∈ parts (used s)⟧ ⟹
    (∃SK. K = SesK SK ∧ (Owner n, Crypt (SesK SK) (Pwd n)) ∈ s) ∨
    {Pwd n, Key K} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_pwd_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_crypt_num_start:
 "⟦s ⊢ s'; Crypt (SesK SK) (Num 0) ∈ parts (used s');
    Crypt (SesK SK) (Num 0) ∉ parts (used s)⟧ ⟹
  (∃n. (Asset n, Crypt (SesK SK) (Num 0)) ∈ s') ∨ SesKey SK ∈ spied s'"
by (simp add: rel_def, (erule disjE, (erule exE)+, simp add: parts_insert image_iff)+,
 blast, (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | erule disjE, simp, drule parts_enc |
 drule parts_sep | drule parts_con), simp+)?)+)

proposition parts_crypt_num:
 "⟦s0 ⊨ s; Crypt (SesK SK) (Num 0) ∈ parts (used s)⟧ ⟹
    (∃n. (Asset n, Crypt (SesK SK) (Num 0)) ∈ s) ∨ SesKey SK ∈ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_num_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_crypt_mult_start:
 "⟦s ⊢ s'; Crypt (SesK SK) (A ⊗ B) ∈ parts (used s');
    Crypt (SesK SK) (A ⊗ B) ∉ parts (used s)⟧ ⟹
  B ∈ fst (snd SK) ∧ (∃n C. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s') ∨
  {A ⊗ B, SesKey SK} ⊆ spied s"
by (simp add: rel_def, (erule disjE, (erule exE)+, simp add: parts_insert image_iff)+,
 blast, (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | erule disjE, simp, drule parts_enc |
 drule parts_sep | drule parts_con), simp+)?)+)

proposition parts_crypt_mult:
 "⟦s0 ⊨ s; Crypt (SesK SK) (A ⊗ B) ∈ parts (used s)⟧ ⟹
    B ∈ fst (snd SK) ∧ (∃n C. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s) ∨
    {A ⊗ B, SesKey SK} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_crypt_mult_start, assumption+,
 drule converse_rtrancl_into_rtrancl, assumption, drule state_subset [of _ s],
 drule spied_subset [of _ s], blast)


proposition parts_mult_start:
 "⟦s ⊢ s'; A ⊗ B ∈ parts (used s'); A ⊗ B ∉ parts (used s)⟧ ⟹
    (∃n SK. A = Auth_PriK n ∧ (Asset n, ⦃Num 2, PubKey B⦄) ∈ s' ∧
      Crypt (SesK SK) (A ⊗ B) ∈ parts (used s')) ∨
    {PriKey A, PriKey B} ⊆ spied s'"
by (simp add: rel_def, (erule disjE, (erule exE)+, simp add: parts_insert image_iff)+,
 blast, (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | drule parts_enc | drule parts_sep | drule parts_con), simp+)?)+)

proposition parts_mult:
 "⟦s0 ⊨ s; A ⊗ B ∈ parts (used s)⟧ ⟹
    (∃n. A = Auth_PriK n ∧ (Asset n, ⦃Num 2, PubKey B⦄) ∈ s) ∨
    {PriKey A, PriKey B} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, frule parts_mult_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_mpair_key_start:
 "⟦s ⊢ s'; ⦃X, Y⦄ ∈ parts (used s'); ⦃X, Y⦄ ∉ parts (used s);
    X = Key K ∨ Y = Key K ∧ K ∉ range PubK⟧ ⟹
  {X, Y} ⊆ spied s'"
by (erule disjE, simp_all add: rel_def,
 (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | drule parts_enc |
 drule parts_sep | erule disjE, simp, drule parts_con), simp+)?)+)

proposition parts_mpair_key:
 "⟦s0 ⊨ s; ⦃X, Y⦄ ∈ parts (used s);
    X = Key K ∨ Y = Key K ∧ K ∉ range PubK⟧ ⟹
  {X, Y} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 blast, (erule exE)+, (erule conjE)+, frule parts_mpair_key_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_mpair_pwd_start:
 "⟦s ⊢ s'; ⦃X, Y⦄ ∈ parts (used s'); ⦃X, Y⦄ ∉ parts (used s);
    X = Pwd n ∨ Y = Pwd n⟧ ⟹
  {X, Y} ⊆ spied s'"
by (erule disjE, simp_all add: rel_def,
 (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | drule parts_enc |
 drule parts_sep | erule disjE, simp, drule parts_con), simp+)?)+)

proposition parts_mpair_pwd:
 "⟦s0 ⊨ s; ⦃X, Y⦄ ∈ parts (used s); X = Pwd n ∨ Y = Pwd n⟧ ⟹
    {X, Y} ⊆ spied s"
by (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 blast, (erule exE)+, (erule conjE)+, frule parts_mpair_pwd_start, assumption+,
 (drule state_subset)+, blast)


proposition parts_pubkey_false_start:
  assumes
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "Crypt (SesK SK) (PubKey C) ∈ parts (used s')" and
    D: "Crypt (SesK SK) (PubKey C) ∉ parts (used s)" and
    E: "∀n. (Owner n, SesKey SK) ∉ s'" and
    F: "SesKey SK ∉ spied s'"
  shows False
proof -
  have "C ∈ snd (snd SK) ∧ ((∃n. (Owner n, SesKey SK) ∈ s') ∨
    (∃n B. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s')) ∨
    SesKey SK ∈ spied s'"
    (is "?P C ∧ ((∃n. ?Q n s') ∨ (∃n B. ?R n B C s')) ∨ ?S s'")
    by (rule parts_crypt_pubkey_start [OF B C D])
  then obtain n B where "?P C" and "?R n B C s'"
    using E and F by blast
  moreover have "¬ ?R n B C s"
    using D by blast
  ultimately have "∃D. Crypt (SesK SK) (PubKey D) ∈ used s"
    (is "∃D. ?U D")
    using B by (auto simp add: rel_def)
  then obtain D where "?U D" ..
  hence "?P D ∧ ((∃n. ?Q n s) ∨ (∃n B. ?R n B D s)) ∨ ?S s"
    by (rule_tac parts_crypt_pubkey [OF A], blast)
  moreover have G: "s ⊆ s'"
    by (rule state_subset, insert B, simp)
  have "∀n. (Owner n, SesKey SK) ∉ s"
    by (rule allI, rule notI, drule subsetD [OF G], insert E, simp)
  moreover have H: "spied s ⊆ spied s'"
    by (rule Image_mono [OF G], simp)
  have "SesKey SK ∉ spied s"
    by (rule notI, drule subsetD [OF H], insert F, contradiction)
  ultimately obtain n' B' where "?R n' B' D s" by blast
  have "∃A' D'. fst (snd SK) = {A', B'} ∧ snd (snd SK) = {D, D'} ∧
    (Asset n', ⦃Num 2, PubKey B'⦄) ∈ s ∧
    (Asset n', ⦃Num 4, PubKey D'⦄) ∈ s ∧
    ?U D' ∧ (Asset n', PubKey B') ∈ s"
    by (rule asset_iv_state [OF A ‹?R n' B' D s›])
  then obtain D' where "snd (snd SK) = {D, D'}" and "?U D'" by blast
  hence "Crypt (SesK SK) (PubKey C) ∈ parts (used s)"
    using ‹?P C› and ‹?U D› by auto
  thus False
    using D by contradiction
qed

proposition parts_pubkey_false:
 "⟦s0 ⊨ s; Crypt (SesK SK) (PubKey C) ∈ parts (used s);
    ∀n. (Owner n, SesKey SK) ∉ s; SesKey SK ∉ spied s⟧ ⟹
  False"
proof (drule rtrancl_start, assumption, subst parts_init, simp add: Range_iff image_def,
 (erule exE)+, (erule conjE)+, erule parts_pubkey_false_start, assumption+,
 rule allI, rule_tac [!] notI)
  fix v n
  assume "(Owner n, SesKey SK) ∈ v" and "v ⊨ s"
  hence "(Owner n, SesKey SK) ∈ s"
    by (erule_tac rev_subsetD, rule_tac state_subset)
  moreover assume "∀n. (Owner n, SesKey SK) ∉ s"
  ultimately show False by simp
next
  fix v
  assume "SesKey SK ∈ spied v" and "v ⊨ s"
  hence "SesKey SK ∈ spied s"
    by (erule_tac rev_subsetD, rule_tac spied_subset)
  moreover assume "SesKey SK ∉ spied s"
  ultimately show False by contradiction
qed


proposition asset_ii_spied_start:
  assumes
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "PriKey B ∈ spied s'" and
    D: "PriKey B ∉ spied s" and
    E: "(Asset n, ⦃Num 2, PubKey B⦄) ∈ s"
  shows "Auth_PriKey n ∈ spied s ∧
    (∃C SK. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s)"
    (is "_ ∧ (∃C SK. ?P n C SK s)")
proof -
  have "∃A. (A ⊗ B ∈ spied s ∨ B ⊗ A ∈ spied s) ∧ PriKey A ∈ spied s"
  proof (insert B C D, auto simp add: rel_def, rule_tac [!] FalseE)
    assume "Key (PriK B) ∉ used s"
    moreover have "PriKey B ∈ used s"
      by (rule asset_ii_used [OF A, THEN mp, OF E])
    ultimately show False by simp
  next
    fix K
    assume "(Spy, Crypt K (Key (PriK B))) ∈ s"
    hence "Crypt K (PriKey B) ∈ parts (used s)" by auto
    hence "(∃m. K = Auth_ShaKey m ∧
      (Asset m, Crypt (Auth_ShaKey m) (PriKey B)) ∈ s) ∨
      {PriKey B, Key K} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_crypt_prikey [OF A])
    then obtain m where "?P m"
      using D by blast
    thus False
      by (rule asset_i_asset_ii [OF A _ E])
  next
    fix Y
    assume "(Spy, ⦃Key (PriK B), Y⦄) ∈ s"
    hence "⦃PriKey B, Y⦄ ∈ parts (used s)" by auto
    hence "{PriKey B, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK B"], simp)
    thus False
      using D by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (PriK B)⦄) ∈ s"
    hence "⦃X, PriKey B⦄ ∈ parts (used s)" by auto
    hence "{X, PriKey B} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK B"], simp add: image_def)
    thus False
      using D by simp
  qed
  then obtain A where F: "PriKey A ∈ spied s" and
    "A ⊗ B ∈ spied s ∨ B ⊗ A ∈ spied s"
    by blast
  hence "A ⊗ B ∈ parts (used s) ∨ B ⊗ A ∈ parts (used s)" by blast
  moreover have "B ⊗ A ∉ parts (used s)"
  proof
    assume "B ⊗ A ∈ parts (used s)"
    hence "(∃m. B = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey A⦄) ∈ s) ∨
      {PriKey B, PriKey A} ⊆ spied s"
      by (rule parts_mult [OF A])
    then obtain m where "B = Auth_PriK m"
      using D by blast
    hence "(Asset n, ⦃Num 2, Auth_PubKey m⦄) ∈ s"
      using E by simp
    thus False
      by (rule auth_pubkey_asset_ii [OF A])
  qed
  ultimately have "A ⊗ B ∈ parts (used s)" by simp
  with A have "∃u v. s0 ⊨ u ∧ u ⊢ v ∧ v ⊨ s ∧
    A ⊗ B ∉ parts (used u) ∧ A ⊗ B ∈ parts (used v)"
    by (rule rtrancl_start, subst parts_init, simp add: Range_iff image_def)
  then obtain u v where G: "u ⊢ v" and H: "v ⊨ s" and
    I: "A ⊗ B ∉ parts (used u)" and "A ⊗ B ∈ parts (used v)"
    by blast
  hence "(∃m SK. A = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey B⦄) ∈ v ∧
    Crypt (SesK SK) (A ⊗ B) ∈ parts (used v)) ∨
    {PriKey A, PriKey B} ⊆ spied v"
    by (rule_tac parts_mult_start, simp_all)
  moreover have "PriKey B ∉ spied v"
  proof
    assume "PriKey B ∈ spied v"
    hence "PriKey B ∈ spied s"
      by (rule rev_subsetD, rule_tac spied_subset [OF H])
    thus False
      using D by contradiction
  qed
  ultimately obtain m SK where
    J: "Crypt (SesK SK) (A ⊗ B) ∈ parts (used v)" and
    "A = Auth_PriK m" and "(Asset m, ⦃Num 2, PubKey B⦄) ∈ v"
    by blast
  moreover from this have "(Asset m, ⦃Num 2, PubKey B⦄) ∈ s"
    by (erule_tac rev_subsetD, rule_tac state_subset [OF H])
  hence "m = n"
    by (rule asset_ii_unique [OF A _ E])
  ultimately have K: "Auth_PriKey n ∈ spied s"
    using F by simp
  have "Crypt (SesK SK) (A ⊗ B) ∉ parts (used u)"
    using I by blast
  hence "B ∈ fst (snd SK) ∧ (∃m C. ?P m C SK v) ∨
    {A ⊗ B, SesKey SK} ⊆ spied u"
    by (rule parts_crypt_mult_start [OF G J])
  moreover have "A ⊗ B ∉ spied u"
    using I by blast
  ultimately obtain m' C where "?P m' C SK v" by blast
  hence "?P m' C SK s"
    by (rule rev_subsetD, rule_tac state_subset [OF H])
  moreover from this have "∃A' D. fst (snd SK) = {A', B} ∧
    snd (snd SK) = {C, D} ∧ (Asset m', ⦃Num 2, PubKey B⦄) ∈ s ∧
    (Asset m', ⦃Num 4, PubKey D⦄) ∈ s ∧
    Crypt (SesK SK) (PubKey D) ∈ used s ∧ (Asset m', PubKey B) ∈ s"
    by (rule asset_iv_state [OF A])
  hence "(Asset m', ⦃Num 2, PubKey B⦄) ∈ s" by blast
  hence "m' = n"
    by (rule asset_ii_unique [OF A _ E])
  ultimately show ?thesis
    using K by blast
qed

proposition asset_ii_spied:
  assumes
    A: "s0 ⊨ s" and
    B: "PriKey B ∈ spied s" and
    C: "(Asset n, ⦃Num 2, PubKey B⦄) ∈ s"
  shows "Auth_PriKey n ∈ spied s ∧
    (∃C SK. (Asset n, Token n (Auth_PriK n) B C SK) ∈ s)"
    (is "?P s")
proof -
  have "∃u v. s0 ⊨ u ∧ u ⊢ v ∧ v ⊨ s ∧
    (Asset n, ⦃Num 2, PubKey B⦄) ∉ u ∧ (Asset n, ⦃Num 2, PubKey B⦄) ∈ v"
    using A and C by (rule rtrancl_start, auto)
  then obtain u v where "v ⊨ s" and "(Asset n, ⦃Num 2, PubKey B⦄) ∉ u" and
    D: "s0 ⊨ u" and E: "u ⊢ v" and F: "(Asset n, ⦃Num 2, PubKey B⦄) ∈ v"
    by blast
  moreover from this have "PriKey B ∉ spied v"
    by (auto simp add: rel_def)
  ultimately have "∃w x. v ⊨ w ∧ w ⊢ x ∧ x ⊨ s ∧
    PriKey B ∉ spied w ∧ PriKey B ∈ spied x"
    using B by (rule_tac rtrancl_start, simp_all)
  then obtain w x where "PriKey B ∉ spied w" and "PriKey B ∈ spied x" and
    G: "v ⊨ w" and H: "w ⊢ x" and I: "x ⊨ s"
    by blast
  moreover from this have "s0 ⊨ w"
    using D and E by simp
  moreover have "(Asset n, ⦃Num 2, PubKey B⦄) ∈ w"
    by (rule rev_subsetD [OF F], rule state_subset [OF G])
  ultimately have "?P w"
    by (rule_tac asset_ii_spied_start, simp_all)
  moreover have "w ⊆ s"
    using H and I by (rule_tac state_subset, simp)
  ultimately show ?thesis by blast
qed


proposition asset_iv_unique:
  assumes
    A: "s0 ⊨ s" and
    B: "(Asset m, Token m (Auth_PriK m) B C' SK') ∈ s" and
    C: "(Asset n, Token n (Auth_PriK n) B C SK) ∈ s"
      (is "?P n C SK s")
  shows "m = n ∧ C' = C ∧ SK' = SK"
proof (subst (2) cases_simp [of "m = n", symmetric], simp, rule conjI, rule impI,
 rule ccontr)
  assume D: "¬ (C' = C ∧ SK' = SK)" and "m = n"
  moreover have "∃u v. s0 ⊨ u ∧ u ⊢ v ∧ v ⊨ s ∧
    ¬ (?P m C' SK' u ∧ ?P n C SK u) ∧ ?P m C' SK' v ∧ ?P n C SK v"
    using B and C by (rule_tac rtrancl_start [OF A], auto)
  ultimately obtain u v where E: "s0 ⊨ u" and F: "u ⊢ v" and
    G: "?P n C' SK' v" and H: "?P n C SK v" and
    "¬ ?P n C' SK' u ∨ ¬ ?P n C SK u"
    by blast
  moreover {
    assume I: "¬ ?P n C' SK' u"
    hence "?P n C SK u"
      by (insert D F G H, auto simp add: rel_def)
    hence "∃A D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
      (Asset n, ⦃Num 2, PubKey B⦄) ∈ u ∧ (Asset n, ⦃Num 4, PubKey D⦄) ∈ u ∧
      Crypt (SesK SK) (PubKey D) ∈ used u ∧ (Asset n, PubKey B) ∈ u"
      by (rule asset_iv_state [OF E])
    moreover have "(Asset n, PubKey B) ∉ u"
      by (insert F G I, auto simp add: rel_def)
    ultimately have False by simp
  }
  moreover {
    assume I: "¬ ?P n C SK u"
    hence "?P n C' SK' u"
      by (insert D F G H, auto simp add: rel_def)
    hence "∃A D. fst (snd SK') = {A, B} ∧ snd (snd SK') = {C', D} ∧
      (Asset n, ⦃Num 2, PubKey B⦄) ∈ u ∧ (Asset n, ⦃Num 4, PubKey D⦄) ∈ u ∧
      Crypt (SesK SK') (PubKey D) ∈ used u ∧ (Asset n, PubKey B) ∈ u"
      by (rule asset_iv_state [OF E])
    moreover have "(Asset n, PubKey B) ∉ u"
      by (insert F H I, auto simp add: rel_def)
    ultimately have False by simp
  }
  ultimately show False by blast
next
  have "∃A D. fst (snd SK') = {A, B} ∧ snd (snd SK') = {C', D} ∧
    (Asset m, ⦃Num 2, PubKey B⦄) ∈ s ∧ (Asset m, ⦃Num 4, PubKey D⦄) ∈ s ∧
    Crypt (SesK SK') (PubKey D) ∈ used s ∧ (Asset m, PubKey B) ∈ s"
    (is "?Q m C' SK'")
    by (rule asset_iv_state [OF A B])
  hence "(Asset m, ⦃Num 2, PubKey B⦄) ∈ s" by blast
  moreover have "?Q n C SK"
    by (rule asset_iv_state [OF A C])
  hence "(Asset n, ⦃Num 2, PubKey B⦄) ∈ s" by blast
  ultimately show "m = n"
    by (rule asset_ii_unique [OF A])
qed


theorem sigkey_secret:
 "s0 ⊨ s ⟹ SigKey ∉ spied s"
proof (erule rtrancl_induct, simp add: image_def)
  fix s s'
  assume
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "SigKey ∉ spied s"
  show "SigKey ∉ spied s'"
  proof (insert B C, auto simp add: rel_def)
    fix K
    assume "(Spy, Crypt K SigKey) ∈ s"
    hence "Crypt K SigKey ∈ parts (used s)" by blast
    hence "{SigKey, Key K} ⊆ spied s"
      by (rule parts_crypt_key [OF A], simp add: image_def)
    with C show False by simp
  next
    fix Y
    assume "(Spy, ⦃SigKey, Y⦄) ∈ s"
    hence "⦃SigKey, Y⦄ ∈ parts (used s)" by blast
    hence "{SigKey, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "SigK"], simp)
    with C show False by simp
  next
    fix X
    assume "(Spy, ⦃X, SigKey⦄) ∈ s"
    hence "⦃X, SigKey⦄ ∈ parts (used s)" by blast
    hence "{X, SigKey} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "SigK"], simp add: image_def)
    with C show False by simp
  qed
qed

proposition parts_sign_start:
  assumes A: "s0 ⊨ s"
  shows "⟦s ⊢ s'; Sign n A ∈ parts (used s'); Sign n A ∉ parts (used s)⟧ ⟹
    A = Auth_PriK n"
by (simp add: rel_def, (((erule disjE)?, (erule exE)+, simp add: parts_insert image_iff)+,
 ((drule parts_dec | erule disjE, insert sigkey_secret [OF A], simp, drule parts_enc |
 drule parts_sep | drule parts_con), simp+)?)+)

proposition parts_sign:
 "⟦s0 ⊨ s; Sign n A ∈ parts (used s)⟧ ⟹
    A = Auth_PriK n"
by (rule classical, drule rtrancl_start, assumption, subst parts_init, simp add:
 Range_iff image_def, (erule exE)+, (erule conjE)+, drule parts_sign_start)


theorem auth_shakey_secret:
 "⟦s0 ⊨ s; n ∉ bad_shakey⟧ ⟹
    Key (Auth_ShaKey n) ∉ spied s"
proof (erule rtrancl_induct, simp add: image_def)
  fix s s'
  assume
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "Key (Auth_ShaKey n) ∉ spied s"
  show "Key (Auth_ShaKey n) ∉ spied s'"
  proof (insert B C, auto simp add: rel_def)
    fix K
    assume "(Spy, Crypt K (Key (ShaK (Auth_ShaK n)))) ∈ s"
    hence "Crypt K (Key (Auth_ShaKey n)) ∈ parts (used s)" by auto
    hence "{Key (Auth_ShaKey n), Key K} ⊆ spied s"
      by (rule parts_crypt_key [OF A], simp add: image_def)
    with C show False by simp
  next
    fix Y
    assume "(Spy, ⦃Key (ShaK (Auth_ShaK n)), Y⦄) ∈ s"
    hence "⦃Key (Auth_ShaKey n), Y⦄ ∈ parts (used s)" by auto
    hence "{Key (Auth_ShaKey n), Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "Auth_ShaKey n"], simp)
    with C show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (ShaK (Auth_ShaK n))⦄) ∈ s"
    hence "⦃X, Key (Auth_ShaKey n)⦄ ∈ parts (used s)" by auto
    hence "{X, Key (Auth_ShaKey n)} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "Auth_ShaKey n"],
       simp add: image_def)
    with C show False by simp
  qed
qed


theorem auth_prikey_secret:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_prikey"
  shows "Auth_PriKey n ∉ spied s"
proof
  assume "Auth_PriKey n ∈ spied s"
  moreover have "Auth_PriKey n ∉ spied s0"
    using B by auto
  ultimately have "∃u v. s0 ⊨ u ∧ u ⊢ v ∧ v ⊨ s ∧
    Auth_PriKey n ∉ spied u ∧ Auth_PriKey n ∈ spied v"
    by (rule rtrancl_start [OF A])
  then obtain u v where C: "s0 ⊨ u" and D: "u ⊢ v" and
    E: "Auth_PriKey n ∉ spied u" and F: "Auth_PriKey n ∈ spied v"
    by blast
  have "∃B. (Auth_PriK n ⊗ B ∈ spied u ∨ B ⊗ Auth_PriK n ∈ spied u) ∧
    PriKey B ∈ spied u"
  proof (insert D E F, auto simp add: rel_def, rule_tac [!] FalseE)
    assume "Key (PriK (Auth_PriK n)) ∉ used u"
    moreover have "Auth_PriKey n ∈ used u"
      by (rule auth_prikey_used [OF C])
    ultimately show False by simp
  next
    fix K
    assume "(Spy, Crypt K (Key (PriK (Auth_PriK n)))) ∈ u"
    hence "Crypt K (PriKey (Auth_PriK n)) ∈ parts (used u)" by auto
    hence "(∃m. K = Auth_ShaKey m ∧
      (Asset m, Crypt (Auth_ShaKey m) (PriKey (Auth_PriK n))) ∈ u) ∨
      {PriKey (Auth_PriK n), Key K} ⊆ spied u"
      by (rule parts_crypt_prikey [OF C])
    then obtain m where
      "(Asset m, Crypt (Auth_ShaKey m) (Auth_PriKey n)) ∈ u"
      using E by auto
    thus False
      by (rule auth_prikey_asset_i [OF C])
  next
    fix Y
    assume "(Spy, ⦃Key (PriK (Auth_PriK n)), Y⦄) ∈ u"
    hence "⦃Auth_PriKey n, Y⦄ ∈ parts (used u)" by auto
    hence "{Auth_PriKey n, Y} ⊆ spied u"
      by (rule parts_mpair_key [OF C, where K = "PriK (Auth_PriK n)"], simp)
    thus False
      using E by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (PriK (Auth_PriK n))⦄) ∈ u"
    hence "⦃X, Auth_PriKey n⦄ ∈ parts (used u)" by auto
    hence "{X, Auth_PriKey n} ⊆ spied u"
      by (rule parts_mpair_key [OF C, where K = "PriK (Auth_PriK n)"], simp
       add: image_def)
    thus False
      using E by simp
  qed
  then obtain B where G: "PriKey B ∈ spied u" and
    "Auth_PriK n ⊗ B ∈ spied u ∨ B ⊗ Auth_PriK n ∈ spied u"
    by blast
  hence "Auth_PriK n ⊗ B ∈ parts (used u) ∨ B ⊗ Auth_PriK n ∈ parts (used u)"
    by blast
  moreover have "B ⊗ Auth_PriK n ∉ parts (used u)"
  proof
    assume "B ⊗ Auth_PriK n ∈ parts (used u)"
    hence "(∃m. B = Auth_PriK m ∧
      (Asset m, ⦃Num 2, PubKey (Auth_PriK n)⦄) ∈ u) ∨
      {PriKey B, PriKey (Auth_PriK n)} ⊆ spied u"
      by (rule parts_mult [OF C])
    then obtain m where "(Asset m, ⦃Num 2, Auth_PubKey n⦄) ∈ u"
      using E by auto
    thus False
      by (rule auth_pubkey_asset_ii [OF C])
  qed
  ultimately have "Auth_PriK n ⊗ B ∈ parts (used u)" by simp
  hence "(∃m. Auth_PriK n = Auth_PriK m ∧
    (Asset m, ⦃Num 2, PubKey B⦄) ∈ u) ∨
    {PriKey (Auth_PriK n), PriKey B} ⊆ spied u"
    by (rule parts_mult [OF C])
  then obtain m where "Auth_PriK n = Auth_PriK m" and
    "(Asset m, ⦃Num 2, PubKey B⦄) ∈ u"
    using E by auto
  moreover from this have "Auth_PriKey m ∈ spied u ∧
    (∃C SK. (Asset m, Token m (Auth_PriK m) B C SK) ∈ u)"
    by (rule_tac asset_ii_spied [OF C G])
  ultimately show False
    using E by simp
qed

proposition asset_ii_secret:
 "⟦s0 ⊨ s; n ∉ bad_prikey; (Asset n, ⦃Num 2, PubKey B⦄) ∈ s⟧ ⟹
    PriKey B ∉ spied s"
by (rule notI, frule asset_ii_spied, assumption+, drule auth_prikey_secret, simp+)


proposition asset_i_secret [rule_format]:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey"
  shows "(Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s ⟶
    PriKey S ∉ spied s"
proof (rule rtrancl_induct [OF A], simp add: image_def, rule impI)
  fix s s'
  assume
    C: "s0 ⊨ s" and
    D: "s ⊢ s'" and
    E: "(Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s ⟶
      PriKey S ∉ spied s" and
    F: "(Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s'"
  show "PriKey S ∉ spied s'"
  proof (insert D E F, auto simp add: rel_def)
    assume "(Asset n, Crypt (ShaK (Auth_ShaK n)) (Key (PriK S))) ∈ s"
    hence "(Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s" by simp
    hence "PriKey S ∈ used s"
      by (rule asset_i_used [OF C, THEN mp])
    moreover assume "Key (PriK S) ∉ used s"
    ultimately show False by simp
  next
    fix K
    assume "(Spy, Crypt K (Key (PriK S))) ∈ s"
    hence "Crypt K (PriKey S) ∈ parts (used s)" by auto
    hence "(∃m. K = Auth_ShaKey m ∧
      (Asset m, Crypt (Auth_ShaKey m) (PriKey S)) ∈ s) ∨
      {PriKey S, Key K} ⊆ spied s"
      (is "(∃m. ?P m ∧ ?Q m) ∨ _")
      by (rule parts_crypt_prikey [OF C])
    moreover assume "(Spy, Key (PriK S)) ∉ s"
    ultimately obtain m where G: "?P m ∧ ?Q m" by auto
    hence "?Q m" ..
    moreover assume
      "(Asset n, Crypt (ShaK (Auth_ShaK n)) (Key (PriK S))) ∈ s"
    hence "(Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s" by simp
    ultimately have "m = n"
      by (rule asset_i_unique [OF C])
    moreover assume "(Spy, Key (InvK K)) ∈ s"
    ultimately have "Key (Auth_ShaKey n) ∈ spied s"
      using G by simp
    moreover have "Key (Auth_ShaKey n) ∉ spied s"
      by (rule auth_shakey_secret [OF C B])
    ultimately show False by contradiction
  next
    fix B
    assume "(Spy, S ⊗ B) ∈ s"
    hence "S ⊗ B ∈ parts (used s)" by blast
    hence "(∃m. S = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey B⦄) ∈ s) ∨
      {PriKey S, PriKey B} ⊆ spied s"
      (is "(∃m. ?P m ∧ _) ∨ _")
      by (rule parts_mult [OF C])
    moreover assume "(Spy, Key (PriK S)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume
      "(Asset n, Crypt (ShaK (Auth_ShaK n)) (Key (PriK S))) ∈ s"
    ultimately have "(Asset n, Crypt (Auth_ShaKey n) (Auth_PriKey m)) ∈ s"
      by simp
    thus False
      by (rule auth_prikey_asset_i [OF C])
  next
    fix A
    assume "(Spy, A ⊗ S) ∈ s"
    hence "A ⊗ S ∈ parts (used s)" by blast
    hence "(∃m. A = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey S⦄) ∈ s) ∨
      {PriKey A, PriKey S} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_mult [OF C])
    moreover assume "(Spy, Key (PriK S)) ∉ s"
    ultimately obtain m where "?P m" by auto
    assume "(Asset n, Crypt (ShaK (Auth_ShaK n)) (Key (PriK S))) ∈ s"
    hence "(Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s" by simp
    thus False
      by (rule asset_i_asset_ii [OF C _ ‹?P m›])
  next
    fix Y
    assume "(Spy, ⦃Key (PriK S), Y⦄) ∈ s"
    hence "⦃PriKey S, Y⦄ ∈ parts (used s)" by auto
    hence "{PriKey S, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF C, where K = "PriK S"], simp)
    moreover assume "(Spy, Key (PriK S)) ∉ s"
    ultimately show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (PriK S)⦄) ∈ s"
    hence "⦃X, PriKey S⦄ ∈ parts (used s)" by auto
    hence "{X, PriKey S} ⊆ spied s"
      by (rule parts_mpair_key [OF C, where K = "PriK S"], simp add: image_def)
    moreover assume "(Spy, Key (PriK S)) ∉ s"
    ultimately show False by simp
  qed
qed

proposition owner_ii_secret [rule_format]:
 "s0 ⊨ s ⟹
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ⟶
  PriKey A ∉ spied s"
proof (erule rtrancl_induct, simp add: image_def, rule impI)
  fix s s'
  assume
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "(Owner n, ⦃Num 1, PubKey A⦄) ∈ s ⟶ PriKey A ∉ spied s" and
    D: "(Owner n, ⦃Num 1, PubKey A⦄) ∈ s'"
  show "PriKey A ∉ spied s'"
  proof (insert B C D, auto simp add: rel_def)
    assume "(Owner n, ⦃Num (Suc 0), Key (PubK A)⦄) ∈ s"
    hence "(Owner n, ⦃Num 1, PubKey A⦄) ∈ s" by simp
    hence "PriKey A ∈ used s"
      by (rule owner_ii_used [OF A, THEN mp])
    moreover assume "Key (PriK A) ∉ used s"
    ultimately show False by simp
  next
    fix K
    assume "(Spy, Crypt K (Key (PriK A))) ∈ s"
    hence "Crypt K (PriKey A) ∈ parts (used s)" by auto
    hence "(∃m. K = Auth_ShaKey m ∧
      (Asset m, Crypt (Auth_ShaKey m) (PriKey A)) ∈ s) ∨
      {PriKey A, Key K} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_crypt_prikey [OF A])
    moreover assume "(Spy, Key (PriK A)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Owner n, ⦃Num (Suc 0), Key (PubK A)⦄) ∈ s"
    hence "(Owner n, ⦃Num 1, PubKey A⦄) ∈ s" by simp
    ultimately show False
      by (rule asset_i_owner_ii [OF A])
  next
    fix B
    assume "(Spy, A ⊗ B) ∈ s"
    hence "A ⊗ B ∈ parts (used s)" by blast
    hence "(∃m. A = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey B⦄) ∈ s) ∨
      {PriKey A, PriKey B} ⊆ spied s"
      (is "(∃m. ?P m ∧ _) ∨ _")
      by (rule parts_mult [OF A])
    moreover assume "(Spy, Key (PriK A)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Owner n, ⦃Num (Suc 0), Key (PubK A)⦄) ∈ s"
    ultimately have "(Owner n, ⦃Num 1, Auth_PubKey m⦄) ∈ s" by simp
    thus False
      by (rule auth_pubkey_owner_ii [OF A])
  next
    fix B
    assume "(Spy, B ⊗ A) ∈ s"
    hence "B ⊗ A ∈ parts (used s)" by blast
    hence "(∃m. B = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey A⦄) ∈ s) ∨
      {PriKey B, PriKey A} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_mult [OF A])
    moreover assume "(Spy, Key (PriK A)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Owner n, ⦃Num (Suc 0), Key (PubK A)⦄) ∈ s"
    hence "(Owner n, ⦃Num 1, PubKey A⦄) ∈ s" by simp
    ultimately show False
      by (rule asset_ii_owner_ii [OF A])
  next
    fix Y
    assume "(Spy, ⦃Key (PriK A), Y⦄) ∈ s"
    hence "⦃PriKey A, Y⦄ ∈ parts (used s)" by auto
    hence "{PriKey A, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK A"], simp)
    moreover assume "(Spy, Key (PriK A)) ∉ s"
    ultimately show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (PriK A)⦄) ∈ s"
    hence "⦃X, PriKey A⦄ ∈ parts (used s)" by auto
    hence "{X, PriKey A} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK A"], simp add: image_def)
    moreover assume "(Spy, Key (PriK A)) ∉ s"
    ultimately show False by simp
  qed
qed

proposition seskey_spied [rule_format]:
 "s0 ⊨ s ⟹
    SesKey SK ∈ spied s ⟶
  (∃S A C. fst SK = Some S ∧ A ∈ fst (snd SK) ∧ C ∈ snd (snd SK) ∧
    {PriKey S, PriKey A, PriKey C} ⊆ spied s)"
  (is "_ ⟹ _ ⟶ (∃S A C. ?P S A C s)")
proof (erule rtrancl_induct, simp add: image_def, rule impI)
  fix s s'
  assume
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "SesKey SK ∈ spied s ⟶ (∃S A C. ?P S A C s)" and
    D: "SesKey SK ∈ spied s'"
  show "∃S A C. ?P S A C s'"
  proof (insert B C D, auto simp add: rel_def, blast, rule_tac [!] FalseE)
    fix K
    assume "(Spy, Crypt K (Key (SesK SK))) ∈ s"
    hence "Crypt K (Key (SesK SK)) ∈ parts (used s)" by blast
    hence "{Key (SesK SK), Key K} ⊆ spied s"
      by (rule parts_crypt_key [OF A], simp add: image_def)
    moreover assume "(Spy, Key (SesK SK)) ∉ s"
    ultimately show False by simp
  next
    fix Y
    assume "(Spy, ⦃Key (SesK SK), Y⦄) ∈ s"
    hence "⦃SesKey SK, Y⦄ ∈ parts (used s)" by auto
    hence "{SesKey SK, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "SesK SK"], simp)
    moreover assume "(Spy, Key (SesK SK)) ∉ s"
    ultimately show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (SesK SK)⦄) ∈ s"
    hence "⦃X, SesKey SK⦄ ∈ parts (used s)" by auto
    hence "{X, SesKey SK} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "SesK SK"], simp add: image_def)
    moreover assume "(Spy, Key (SesK SK)) ∉ s"
    ultimately show False by simp
  qed
qed

proposition owner_seskey_shakey:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey" and
    C: "(Owner n, SesKey SK) ∈ s"
  shows "SesKey SK ∉ spied s"
proof
  have "(∃S. fst SK = Some S ∧ Crypt (Auth_ShaKey n) (PriKey S) ∈ used s) ∨
    fst SK = None"
    (is "(∃S. ?P S) ∨ _")
    by (rule owner_seskey_nonce [OF A C])
  moreover assume "SesKey SK ∈ spied s"
  hence D: "∃S A C. fst SK = Some S ∧ A ∈ fst (snd SK) ∧
    C ∈ snd (snd SK) ∧ {PriKey S, PriKey A, PriKey C} ⊆ spied s"
    by (rule seskey_spied [OF A])
  ultimately obtain S where "?P S" by auto
  hence "Crypt (Auth_ShaKey n) (PriKey S) ∈ parts (used s)" by blast
  hence "(∃m. Auth_ShaKey n = Auth_ShaKey m ∧
    (Asset m, Crypt (Auth_ShaKey m) (PriKey S)) ∈ s) ∨
    {PriKey S, Key (Auth_ShaKey n)} ⊆ spied s"
    (is "(∃m. ?Q m ∧ ?R m) ∨ _")
    by (rule parts_crypt_prikey [OF A])
  moreover have "Key (Auth_ShaKey n) ∉ spied s"
    by (rule auth_shakey_secret [OF A B])
  ultimately obtain m where "?Q m" and "?R m" by blast
  hence "m ∉ bad_shakey"
    using B by simp
  hence "PriKey S ∉ spied s"
    by (rule asset_i_secret [OF A _ ‹?R m›])
  moreover have "PriKey S ∈ spied s"
    using D and ‹?P S› by auto
  ultimately show False by contradiction
qed

proposition owner_seskey_prikey:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_prikey" and
    C: "(Owner m, SesKey SK) ∈ s" and
    D: "(Asset n, ⦃Num 2, PubKey B⦄) ∈ s" and
    E: "B ∈ fst (snd SK)"
  shows "SesKey SK ∉ spied s"
proof
  have "∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    (Owner m, ⦃Num 1, PubKey A⦄) ∈ s ∧
    (Owner m, ⦃Num 3, PubKey C⦄) ∈ s ∧
    (Owner m, Crypt (SesK SK) (PubKey D)) ∈ s"
    (is "∃A B C D. ?P A B ∧ _ ∧ ?Q A ∧ _")
    by (rule owner_seskey_other [OF A C])
  then obtain A B' where "?P A B'" and "?Q A" by blast
  assume "SesKey SK ∈ spied s"
  hence "∃S A' C. fst SK = Some S ∧ A' ∈ fst (snd SK) ∧ C ∈ snd (snd SK) ∧
    {PriKey S, PriKey A', PriKey C} ⊆ spied s"
    (is "∃S A' C. _ ∧ ?R A' ∧ _")
    by (rule seskey_spied [OF A])
  then obtain A' where "A' ∈ fst (snd SK)" and "PriKey A' ∈ spied s" (is "?R A'")
    by blast
  hence "{A', A, B} ⊆ {A, B'}"
    using E and ‹?P A B'› by simp
  hence "card {A', A, B} ≤ card {A, B'}"
    by (rule_tac card_mono, simp)
  also have "… ≤ Suc (Suc 0)"
    by (rule card_insert_le_m1, simp_all)
  finally have "card {A', A, B} ≤ Suc (Suc 0)" .
  moreover have "card {A', A, B} = Suc (card {A, B})"
  proof (rule card_insert_disjoint, simp_all, rule conjI, rule_tac [!] notI)
    assume "A' = A"
    hence "?R A"
      using ‹?R A'› by simp
    moreover have "¬ ?R A"
      by (rule owner_ii_secret [OF A ‹?Q A›])
    ultimately show False by contradiction
  next
    assume "A' = B"
    hence "?R B"
      using ‹?R A'› by simp
    moreover have "¬ ?R B"
      by (rule asset_ii_secret [OF A B D])
    ultimately show False by contradiction
  qed
  moreover have "card {A, B} = Suc (card {B})"
  proof (rule card_insert_disjoint, simp_all, rule notI)
    assume "A = B"
    hence "(Asset n, ⦃Num 2, PubKey A⦄) ∈ s"
      using D by simp
    thus False
      by (rule asset_ii_owner_ii [OF A _ ‹?Q A›])
  qed
  ultimately show False by simp
qed

proposition asset_seskey_shakey:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey" and
    C: "(Asset n, SesKey SK) ∈ s"
  shows "SesKey SK ∉ spied s"
proof
  have "∃S. fst SK = Some S ∧
    (Asset n, Crypt (Auth_ShaKey n) (PriKey S)) ∈ s"
    (is "∃S. ?P S ∧ ?Q S")
    by (rule asset_seskey_nonce [OF A C])
  then obtain S where "?P S" and "?Q S" by blast
  have "PriKey S ∉ spied s"
    by (rule asset_i_secret [OF A B ‹?Q S›])
  moreover assume "SesKey SK ∈ spied s"
  hence "∃S A C. fst SK = Some S ∧ A ∈ fst (snd SK) ∧ C ∈ snd (snd SK) ∧
    {PriKey S, PriKey A, PriKey C} ⊆ spied s"
    by (rule seskey_spied [OF A])
  hence "PriKey S ∈ spied s"
    using ‹?P S› by auto
  ultimately show False by contradiction
qed


theorem owner_seskey_unique:
  assumes
    A: "s0 ⊨ s" and
    B: "(Owner m, Crypt (SesK SK) (Pwd m)) ∈ s" and
    C: "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s"
  shows "m = n"
proof (rule ccontr)
  have D: "(Owner m, SesKey SK) ∈ s ∧
    (∃A B C. Token m A B C SK ∈ used s ∧ B ∈ fst (snd SK))"
    (is "?P m ∧ (∃A B C. ?Q m A B C)")
    by (rule owner_v_state [OF A B])
  hence "?P m" by blast
  hence "∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    (Owner m, ⦃Num 1, PubKey A⦄) ∈ s ∧
    (Owner m, ⦃Num 3, PubKey C⦄) ∈ s ∧
    (Owner m, Crypt (SesK SK) (PubKey D)) ∈ s"
    (is "∃A B C D. ?R A B ∧ ?S C D ∧ ?T m A ∧ ?U m C D")
    by (rule owner_seskey_other [OF A])
  then obtain A B where "?R A B" and "?T m A" by blast
  have "?P n ∧ (∃A B C. ?Q n A B C)"
    by (rule owner_v_state [OF A C])
  hence "?P n" by blast
  hence "∃A B C D. ?R A B ∧ ?S C D ∧ ?T n A ∧ ?U n C D"
    by (rule owner_seskey_other [OF A])
  then obtain A' B' where "?R A' B'" and "?T n A'" by blast
  from D obtain A'' B'' C where "?Q m A'' B'' C" by blast
  hence "Token m A'' B'' C SK ∈ parts (used s)" by blast
  hence "Crypt (SesK SK) (A'' ⊗ B'') ∈ parts (used s)" by blast
  hence "B'' ∈ fst (snd SK) ∧
    (∃i C'. (Asset i, Token i (Auth_PriK i) B'' C' SK) ∈ s) ∨
    {A'' ⊗ B'', SesKey SK} ⊆ spied s"
    (is "?V B'' ∧ (∃i C'. ?W i B'' C') ∨ _")
    by (rule parts_crypt_mult [OF A])
  hence "∃D. ?V D ∧ D ∉ {A, A'}"
  proof (rule disjE, (erule_tac conjE, ((erule_tac exE)+)?)+)
    fix i C'
    assume "?V B''" and "?W i B'' C'"
    have "∃A D. ?R A B'' ∧ ?S C' D ∧
      (Asset i, ⦃Num 2, PubKey B''⦄) ∈ s ∧ (Asset i, ⦃Num 4, PubKey D⦄) ∈ s ∧
      Crypt (SesK SK) (PubKey D) ∈ used s ∧ (Asset i, PubKey B'') ∈ s"
      (is "∃A D. _ ∧ _ ∧ ?X i B'' ∧ _")
      by (rule asset_iv_state [OF A ‹?W i B'' C'›])
    hence "?X i B''" by blast
    have "B'' ≠ A"
    proof
      assume "B'' = A"
      hence "?X i A"
        using ‹?X i B''› by simp
      thus False
        by (rule asset_ii_owner_ii [OF A _ ‹?T m A›])
    qed
    moreover have "B'' ≠ A'"
    proof
      assume "B'' = A'"
      hence "?X i A'"
        using ‹?X i B''› by simp
      thus False
        by (rule asset_ii_owner_ii [OF A _ ‹?T n A'›])
    qed
    ultimately show ?thesis
      using ‹?V B''› by blast
  next
    assume "{A'' ⊗ B'', SesKey SK} ⊆ spied s"
    hence "SesKey SK ∈ spied s" by simp
    hence "∃S D E. fst SK = Some S ∧ ?V D ∧ E ∈ snd (snd SK) ∧
      {PriKey S, PriKey D, PriKey E} ⊆ spied s"
      by (rule seskey_spied [OF A])
    then obtain D where "?V D" and "PriKey D ∈ spied s" (is "?X D")
      by blast
    moreover have "D ≠ A"
    proof
      assume "D = A"
      hence "?X A"
        using ‹?X D› by simp
      moreover have "¬ ?X A"
        by (rule owner_ii_secret [OF A ‹?T m A›])
      ultimately show False by contradiction
    qed
    moreover have "D ≠ A'"
    proof
      assume "D = A'"
      hence "?X A'"
        using ‹?X D› by simp
      moreover have "¬ ?X A'"
        by (rule owner_ii_secret [OF A ‹?T n A'›])
      ultimately show False by contradiction
    qed
    ultimately show ?thesis by blast
  qed
  then obtain D where "?V D" and E: "D ∉ {A, A'}" by blast
  hence "{D, A, A'} ⊆ {A, B}"
    using ‹?R A B› and ‹?R A' B'› by blast
  hence "card {D, A, A'} ≤ card {A, B}"
    by (rule_tac card_mono, simp)
  also have "… ≤ Suc (Suc 0)"
    by (rule card_insert_le_m1, simp_all)
  finally have "card {D, A, A'} ≤ Suc (Suc 0)" .
  moreover have "card {D, A, A'} = Suc (card {A, A'})"
    by (rule card_insert_disjoint [OF _ E], simp)
  moreover assume "m ≠ n"
  hence "card {A, A'} = Suc (card {A'})"
  proof (rule_tac card_insert_disjoint, simp_all, erule_tac contrapos_nn)
    assume "A = A'"
    hence "?T n A"
      using ‹?T n A'› by simp
    thus "m = n"
      by (rule owner_ii_unique [OF A ‹?T m A›])
  qed
  ultimately show False by simp
qed


theorem owner_seskey_secret:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey ∩ bad_prikey" and
    C: "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s"
  shows "SesKey SK ∉ spied s"
proof -
  have "(Owner n, SesKey SK) ∈ s ∧
    (∃A B C. Token n A B C SK ∈ used s ∧ B ∈ fst (snd SK))"
    (is "?P ∧ (∃A B C. ?Q A B C ∧ ?R B)")
    by (rule owner_v_state [OF A C])
  then obtain A B C where "?P" and "?Q A B C" and "?R B" by blast
  have "n ∈ bad_shakey ∨ n ∉ bad_shakey" by simp
  moreover {
    assume "n ∈ bad_shakey"
    hence D: "n ∉ bad_prikey"
      using B by simp
    hence "Auth_PriKey n ∉ spied s"
      by (rule auth_prikey_secret [OF A])
    moreover have "Sign n A ∈ parts (used s)"
      using ‹?Q A B C› by blast
    hence "A = Auth_PriK n"
      by (rule parts_sign [OF A])
    hence "?Q (Auth_PriK n) B C"
      using ‹?Q A B C› by simp
    hence "Auth_PriK n ⊗ B ∈ parts (used s)" by blast
    hence "(∃m. Auth_PriK n = Auth_PriK m ∧
      (Asset m, ⦃Num 2, PubKey B⦄) ∈ s) ∨
      {PriKey (Auth_PriK n), PriKey B} ⊆ spied s"
      (is "(∃m. ?S m ∧ ?T m) ∨ _")
      by (rule parts_mult [OF A])
    ultimately obtain m where "?S m" and "?T m" by auto
    hence "m ∉ bad_prikey"
      using D by simp
    hence ?thesis
      by (rule owner_seskey_prikey [OF A _ ‹?P› ‹?T m› ‹?R B›])
  }
  moreover {
    assume "n ∉ bad_shakey"
    hence ?thesis
      by (rule owner_seskey_shakey [OF A _ ‹?P›])
  }
  ultimately show ?thesis ..
qed


theorem owner_num_genuine:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey ∩ bad_prikey" and
    C: "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s" and
    D: "Crypt (SesK SK) (Num 0) ∈ used s"
  shows "(Asset n, Crypt (SesK SK) (Num 0)) ∈ s"
proof -
  have "Crypt (SesK SK) (Num 0) ∈ parts (used s)"
    using D ..
  hence "(∃m. (Asset m, Crypt (SesK SK) (Num 0)) ∈ s) ∨
    SesKey SK ∈ spied s"
    by (rule parts_crypt_num [OF A])
  moreover have E: "SesKey SK ∉ spied s"
    by (rule owner_seskey_secret [OF A B C])
  ultimately obtain m where "(Asset m, Crypt (SesK SK) (Num 0)) ∈ s"
    by blast
  moreover from this have "(Asset m, SesKey SK) ∈ s ∧
    Crypt (SesK SK) (Pwd m) ∈ used s"
    by (rule asset_v_state [OF A])
  hence "Crypt (SesK SK) (Pwd m) ∈ parts (used s)" by blast
  hence "(∃SK'. SesK SK = SesK SK' ∧
    (Owner m, Crypt (SesK SK') (Pwd m)) ∈ s) ∨
    {Pwd m, Key (SesK SK)} ⊆ spied s"
    by (rule parts_crypt_pwd [OF A])
  hence "(Owner m, Crypt (SesK SK) (Pwd m)) ∈ s"
    using E by simp
  hence "m = n"
    by (rule owner_seskey_unique [OF A _ C])
  ultimately show ?thesis by simp
qed


theorem owner_token_genuine:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey ∩ bad_prikey" and
    C: "(Owner n, ⦃Num 3, PubKey C⦄) ∈ s" and
    D: "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s" and
    E: "Token n A B C SK ∈ used s"
  shows "A = Auth_PriK n ∧ B ∈ fst (snd SK) ∧ C ∈ snd (snd SK) ∧
    (Asset n, ⦃Num 2, PubKey B⦄) ∈ s ∧ (Asset n, Token n A B C SK) ∈ s"
    (is "?P n A ∧ ?Q B ∧ ?R C ∧ ?S n B ∧ _")
proof -
  have "Crypt (SesK SK) (Sign n A) ∈ parts (used s)"
    using E by blast
  hence "(Asset n, SesKey SK) ∈ s ∨ SesKey SK ∈ spied s"
    by (rule parts_crypt_sign [OF A])
  moreover have "SesKey SK ∉ spied s"
    by (rule owner_seskey_secret [OF A B D])
  ultimately have "(Asset n, SesKey SK) ∈ s" by simp
  hence "∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    ?S n B ∧ (Asset n, ⦃Num 4, PubKey D⦄) ∈ s ∧
    (Asset n, Token n (Auth_PriK n) B C SK) ∈ s"
    (is "∃A B C D. ?T A B ∧ ?U C D ∧ _ ∧ ?V n D ∧ ?W n B C")
    by (rule asset_seskey_other [OF A])
  then obtain A' B' C' D where
   "?T A' B'" and "?U C' D" and "?S n B'" and "?V n D" and "?W n B' C'"
    by blast
  have "Sign n A ∈ parts (used s)"
    using E by blast
  hence "?P n A"
    by (rule parts_sign [OF A])
  have "Crypt (SesK SK) (A ⊗ B) ∈ parts (used s)"
    using E by blast
  hence "?Q B ∧ (∃m C''. ?W m B C'') ∨ {A ⊗ B, SesKey SK} ⊆ spied s"
    by (rule parts_crypt_mult [OF A])
  moreover have F: "SesKey SK ∉ spied s"
    by (rule owner_seskey_secret [OF A B D])
  ultimately obtain m C'' where "?Q B" and "?W m B C''" by blast
  have "∃A D. ?T A B ∧ ?U C'' D ∧ ?S m B ∧ ?V m D ∧
    Crypt (SesK SK) (PubKey D) ∈ used s ∧ (Asset m, PubKey B) ∈ s"
    by (rule asset_iv_state [OF A ‹?W m B C''›])
  hence "?S m B" by blast
  have "(Owner n, SesKey SK) ∈ s ∧
    (∃A B C. Token n A B C SK ∈ used s ∧ B ∈ fst (snd SK))"
    by (rule owner_v_state [OF A D])
  hence "(Owner n, SesKey SK) ∈ s" by blast
  hence "∃A B C D. ?T A B ∧ ?U C D ∧
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ∧
    (Owner n, ⦃Num 3, PubKey C⦄) ∈ s ∧
    (Owner n, Crypt (SesK SK) (PubKey D)) ∈ s"
    (is "∃A B C D. _ ∧ _ ∧ ?X A ∧ _")
    by (rule owner_seskey_other [OF A])
  then obtain A'' where "?Q A''" and "?X A''" by blast
  have G: "B' = B"
  proof (rule ccontr)
    have "{A'', B', B} ⊆ {A', B'}"
      using ‹?T A' B'› and ‹?Q B› and ‹?Q A''› by simp
    hence "card {A'', B', B} ≤ card {A', B'}"
      by (rule_tac card_mono, simp)
    also have "… ≤ Suc (Suc 0)"
      by (rule card_insert_le_m1, simp_all)
    finally have "card {A'', B', B} ≤ Suc (Suc 0)" .
    moreover have "A'' ∉ {B', B}"
    proof (simp, rule conjI, rule_tac [!] notI)
      assume "A'' = B'"
      hence "?S n A''"
        using ‹?S n B'› by simp
      thus False
        by (rule asset_ii_owner_ii [OF A _ ‹?X A''›])
    next
      assume "A'' = B"
      hence "?S m A''"
        using ‹?S m B› by simp
      thus False
        by (rule asset_ii_owner_ii [OF A _ ‹?X A''›])
    qed
    hence "card {A'', B', B} = Suc (card {B', B})"
      by (rule_tac card_insert_disjoint, simp)
    moreover assume "B' ≠ B"
    hence "card {B', B} = Suc (card {B})"
      by (rule_tac card_insert_disjoint, simp_all)
    ultimately show False by simp
  qed
  hence "?S n B"
    using ‹?S n B'› by simp
  have "Crypt (SesK SK) (PubKey C) ∈ parts (used s)"
    using E by blast
  hence "?R C ∧ ((∃n. (Owner n, SesKey SK) ∈ s) ∨ (∃n B. ?W n B C)) ∨
    SesKey SK ∈ spied s"
    by (rule parts_crypt_pubkey [OF A])
  hence "?R C"
    using F by simp
  hence "C ∈ {C', D}"
    using ‹?U C' D› by simp
  moreover have "C ≠ D"
  proof
    assume "C = D"
    hence "?V n C"
      using ‹?V n D› by simp
    thus False
      by (rule asset_iii_owner_iii [OF A _ C])
  qed
  ultimately have "C = C'" by simp
  hence "(Asset n, Token n A B C SK) ∈ s"
    using G and ‹?P n A› and ‹?W n B' C'› by simp
  thus ?thesis
    using ‹?P n A› and ‹?Q B› and ‹?R C› and ‹?S n B› by simp
qed


theorem pwd_secret:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_pwd ∪ bad_shakey ∩ bad_prikey"
  shows "Pwd n ∉ spied s"
proof (rule rtrancl_induct [OF A], insert B, simp add: image_def)
  fix s s'
  assume
    C: "s0 ⊨ s" and
    D: "s ⊢ s'" and
    E: "Pwd n ∉ spied s"
  show "Pwd n ∉ spied s'"
  proof (insert D E, auto simp add: rel_def)
    fix K
    assume "(Spy, Crypt K (Pwd n)) ∈ s"
    hence "Crypt K (Pwd n) ∈ parts (used s)" by blast
    hence "(∃SK. K = SesK SK ∧ (Owner n, Crypt (SesK SK) (Pwd n)) ∈ s) ∨
      {Pwd n, Key K} ⊆ spied s"
      (is "(∃SK. ?P SK ∧ ?Q SK) ∨ _")
      by (rule parts_crypt_pwd [OF C])
    then obtain SK where "?P SK" and "?Q SK"
      using E by blast
    have "n ∉ bad_shakey ∩ bad_prikey"
      using B by simp
    hence "SesKey SK ∉ spied s"
      by (rule owner_seskey_secret [OF C _ ‹?Q SK›])
    moreover assume "(Spy, Key (InvK K)) ∈ s"
    ultimately show False
      using ‹?P SK› by simp
  next
    fix Y
    assume "(Spy, ⦃Pwd n, Y⦄) ∈ s"
    hence "⦃Pwd n, Y⦄ ∈ parts (used s)" by blast
    hence "{Pwd n, Y} ⊆ spied s"
      by (rule parts_mpair_pwd [OF C, where n = n], simp)
    with E show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Pwd n⦄) ∈ s"
    hence "⦃X, Pwd n⦄ ∈ parts (used s)" by blast
    hence "{X, Pwd n} ⊆ spied s"
      by (rule parts_mpair_pwd [OF C, where n = n], simp)
    with E show False by simp
  qed
qed


theorem asset_seskey_unique:
  assumes
    A: "s0 ⊨ s" and
    B: "(Asset m, Token m (Auth_PriK m) B' C' SK) ∈ s" and
    C: "(Asset n, Token n (Auth_PriK n) B C SK) ∈ s"
      (is "?P n B C SK s")
  shows "m = n ∧ B' = B ∧ C' = C"
proof (subst (2) cases_simp [of "B' = B", symmetric], simp, rule conjI, rule impI,
 insert B C, simp only:, drule asset_iv_unique [OF A], simp, simp, rule ccontr)
  assume "B' ≠ B"
  moreover have "∃A D. fst (snd SK) = {A, B'} ∧ snd (snd SK) = {C', D} ∧
    (Asset m, ⦃Num 2, PubKey B'⦄) ∈ s ∧ (Asset m, ⦃Num 4, PubKey D⦄) ∈ s ∧
    Crypt (SesK SK) (PubKey D) ∈ used s ∧ (Asset m, PubKey B') ∈ s"
    (is "?Q m B' C'")
    by (rule asset_iv_state [OF A B])
  then obtain A where "fst (snd SK) = {A, B'}" and
    "(Asset m, ⦃Num 2, PubKey B'⦄) ∈ s"
    by blast
  moreover have "?Q n B C"
    by (rule asset_iv_state [OF A C])
  hence "B ∈ fst (snd SK)" and "(Asset n, ⦃Num 2, PubKey B⦄) ∈ s"
    by auto
  ultimately have D: "∀A ∈ fst (snd SK).
    ∃i C. (Asset i, ⦃Num 2, PubKey A⦄) ∈ s ∧ ?P i A C SK s"
    using B and C by auto
  have "Crypt (SesK SK) (PubKey C) ∈ parts (used s)"
    using C by blast
  thus False
  proof (rule parts_pubkey_false [OF A], rule_tac allI, rule_tac [!] notI)
    fix i
    assume "(Owner i, SesKey SK) ∈ s"
    hence "∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
      (Owner i, ⦃Num 1, PubKey A⦄) ∈ s ∧
      (Owner i, ⦃Num 3, PubKey C⦄) ∈ s ∧
      (Owner i, Crypt (SesK SK) (PubKey D)) ∈ s"
      by (rule owner_seskey_other [OF A])
    then obtain A where "A ∈ fst (snd SK)" and
      E: "(Owner i, ⦃Num 1, PubKey A⦄) ∈ s"
      by blast
    then obtain j where "(Asset j, ⦃Num 2, PubKey A⦄) ∈ s"
      using D by blast
    thus False
      by (rule asset_ii_owner_ii [OF A _ E])
  next
    assume "SesKey SK ∈ spied s"
    hence "∃S A C. fst SK = Some S ∧ A ∈ fst (snd SK) ∧ C ∈ snd (snd SK) ∧
      {PriKey S, PriKey A, PriKey C} ⊆ spied s"
      (is "?R s")
      by (rule seskey_spied [OF A])
    moreover have "¬ (∃A ∈ fst (snd SK). PriKey A ∈ spied s)"
      (is "¬ ?S s")
    proof
      assume "?S s"
      moreover have "¬ ?S s0"
        by (subst bex_simps, rule ballI, drule bspec [OF D], (erule exE)+,
         erule conjE, rule asset_ii_init [OF A])
      ultimately have "∃u v. s0 ⊨ u ∧ u ⊢ v ∧ v ⊨ s ∧ ¬ ?S u ∧ ?S v"
        by (rule rtrancl_start [OF A])
      then obtain u v A where E: "s0 ⊨ u" and F: "u ⊢ v" and G: "v ⊨ s" and
        H: "¬ ?S u" and I: "A ∈ fst (snd SK)" and J: "PriKey A ∉ spied u" and
        K: "PriKey A ∈ spied v"
        by blast
      then obtain i where "(Asset i, ⦃Num 2, PubKey A⦄) ∈ s"
        using D by blast
      hence "(Asset i, ⦃Num 2, PubKey A⦄) ∈ v"
      proof (rule_tac ccontr, drule_tac rtrancl_start [OF G], simp,
       (erule_tac exE)+, (erule_tac conjE)+)
        fix w x
        assume "w ⊢ x" and "(Asset i, ⦃Num 2, PubKey A⦄) ∉ w" and
          "(Asset i, ⦃Num 2, PubKey A⦄) ∈ x"
        hence "PriKey A ∉ spied w"
          by (auto simp add: rel_def)
        moreover assume "v ⊨ w"
        hence "PriKey A ∈ spied w"
          by (rule_tac rev_subsetD [OF K], rule spied_subset)
        ultimately show False by contradiction
      qed
      hence "(Asset i, ⦃Num 2, PubKey A⦄) ∈ u"
        using F and K by (auto simp add: rel_def)
      hence "Auth_PriKey i ∈ spied u ∧ (∃C SK. ?P i A C SK u)"
        by (rule asset_ii_spied_start [OF E F K J])
      then obtain C' SK' where L: "?P i A C' SK' u" by blast
      moreover have M: "u ⊨ s"
        using F and G by simp
      ultimately have "?P i A C' SK' s"
        by (erule_tac rev_subsetD, rule_tac state_subset)
      moreover obtain j C where "?P j A C SK s"
        using D and I by blast
      ultimately have "i = j ∧ C' = C ∧ SK' = SK"
        by (rule asset_iv_unique [OF A])
      hence "Crypt (SesK SK) (PubKey C) ∈ parts (used u)"
        using L by blast
      thus False
      proof (rule parts_pubkey_false [OF E], rule_tac allI, rule_tac [!] notI)
        fix i
        assume "(Owner i, SesKey SK) ∈ u"
        hence "∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
          (Owner i, ⦃Num 1, PubKey A⦄) ∈ u ∧
          (Owner i, ⦃Num 3, PubKey C⦄) ∈ u ∧
          (Owner i, Crypt (SesK SK) (PubKey D)) ∈ u"
          by (rule owner_seskey_other [OF E])
        then obtain A where "A ∈ fst (snd SK)" and
          N: "(Owner i, ⦃Num 1, PubKey A⦄) ∈ u"
          by blast
        then obtain j where "(Asset j, ⦃Num 2, PubKey A⦄) ∈ s"
          using D by blast
        moreover have "(Owner i, ⦃Num 1, PubKey A⦄) ∈ s"
          by (rule rev_subsetD [OF N], rule state_subset [OF M])
        ultimately show False
          by (rule asset_ii_owner_ii [OF A])
      next
        assume "SesKey SK ∈ spied u"
        hence "?R u"
          by (rule seskey_spied [OF E])
        thus False
          using H by blast
      qed
    qed
    ultimately show False by blast
  qed
qed


theorem asset_seskey_secret:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey ∩ (bad_pwd ∪ bad_prikey)" and
    C: "(Asset n, Crypt (SesK SK) (Num 0)) ∈ s"
  shows "SesKey SK ∉ spied s"
proof -
  have D: "(Asset n, SesKey SK) ∈ s ∧ Crypt (SesK SK) (Pwd n) ∈ used s"
    by (rule asset_v_state [OF A C])
  have "n ∈ bad_shakey ∨ n ∉ bad_shakey" by simp
  moreover {
    assume "n ∈ bad_shakey"
    hence "Pwd n ∉ spied s"
      using B by (rule_tac pwd_secret [OF A], simp)
    moreover have "Crypt (SesK SK) (Pwd n) ∈ parts (used s)"
      using D by blast
    hence "(∃SK'. SesK SK = SesK SK' ∧
      (Owner n, Crypt (SesK SK') (Pwd n)) ∈ s) ∨
      {Pwd n, Key (SesK SK)} ⊆ spied s"
      by (rule parts_crypt_pwd [OF A])
    ultimately have "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s" by simp
    hence ?thesis
      using B by (rule_tac owner_seskey_secret [OF A], simp_all)
  }
  moreover {
    assume "n ∉ bad_shakey"
    hence ?thesis
      using D by (rule_tac asset_seskey_shakey [OF A], simp_all)
  }
  ultimately show ?thesis ..
qed


theorem asset_pwd_genuine:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey ∩ (bad_pwd ∪ bad_prikey)" and
    C: "(Asset n, Crypt (SesK SK) (Num 0)) ∈ s"
  shows "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s"
proof -
  have "(Asset n, SesKey SK) ∈ s ∧ Crypt (SesK SK) (Pwd n) ∈ used s"
    by (rule asset_v_state [OF A C])
  hence "Crypt (SesK SK) (Pwd n) ∈ parts (used s)" by blast
  hence "(∃SK'. SesK SK = SesK SK' ∧
    (Owner n, Crypt (SesK SK') (Pwd n)) ∈ s) ∨
    {Pwd n, Key (SesK SK)} ⊆ spied s"
    by (rule parts_crypt_pwd [OF A])
  moreover have "SesKey SK ∉ spied s"
    by (rule asset_seskey_secret [OF A B C])
  ultimately show ?thesis by simp
qed


theorem asset_token_genuine:
  assumes
    A: "s0 ⊨ s" and
    B: "n ∉ bad_shakey ∩ (bad_pwd ∪ bad_prikey)" and
    C: "(Asset n, ⦃Num 4, PubKey D⦄) ∈ s" and
    D: "(Asset n, Crypt (SesK SK) (Num 0)) ∈ s" and
    E: "D ∈ snd (snd SK)"
  shows "(Owner n, Crypt (SesK SK) (PubKey D)) ∈ s"
proof -
  have "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s"
    by (rule asset_pwd_genuine [OF A B D])
  hence "(Owner n, SesKey SK) ∈ s ∧
    (∃A B C. Token n A B C SK ∈ used s ∧ B ∈ fst (snd SK))"
    by (rule owner_v_state [OF A])
  hence "(Owner n, SesKey SK) ∈ s" ..
  hence "∃A B C D. fst (snd SK) = {A, B} ∧ snd (snd SK) = {C, D} ∧
    (Owner n, ⦃Num 1, PubKey A⦄) ∈ s ∧
    (Owner n, ⦃Num 3, PubKey C⦄) ∈ s ∧
    (Owner n, Crypt (SesK SK) (PubKey D)) ∈ s"
    (is "∃A B C D. _ ∧ ?P C D ∧ _ ∧ ?Q C ∧ ?R D")
    by (rule owner_seskey_other [OF A])
  then obtain C D' where "?P C D'" and "?Q C" and "?R D'" by blast
  have "D ≠ C"
  proof
    assume "D = C"
    hence "?Q D"
      using ‹?Q C› by simp
    thus False
      by (rule asset_iii_owner_iii [OF A C])
  qed
  hence "D = D'"
    using E and ‹?P C D'› by simp
  thus ?thesis
    using ‹?R D'› by simp
qed


proposition owner_iii_secret [rule_format]:
 "s0 ⊨ s ⟹
    (Owner n, ⦃Num 3, PubKey C⦄) ∈ s ⟶
  PriKey C ∉ spied s"
proof (erule rtrancl_induct, simp add: image_def, rule impI)
  fix s s'
  assume
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "(Owner n, ⦃Num 3, PubKey C⦄) ∈ s ⟶ PriKey C ∉ spied s" and
    D: "(Owner n, ⦃Num 3, PubKey C⦄) ∈ s'"
  show "PriKey C ∉ spied s'"
  proof (insert B C D, auto simp add: rel_def)
    assume "(Owner n, ⦃Num 3, Key (PubK C)⦄) ∈ s"
    hence "(Owner n, ⦃Num 3, PubKey C⦄) ∈ s" by simp
    hence "PriKey C ∈ used s"
      by (rule owner_iii_used [OF A, THEN mp])
    moreover assume "Key (PriK C) ∉ used s"
    ultimately show False by simp
  next
    fix K
    assume "(Spy, Crypt K (Key (PriK C))) ∈ s"
    hence "Crypt K (PriKey C) ∈ parts (used s)" by auto
    hence "(∃m. K = Auth_ShaKey m ∧
      (Asset m, Crypt (Auth_ShaKey m) (PriKey C)) ∈ s) ∨
      {PriKey C, Key K} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_crypt_prikey [OF A])
    moreover assume "(Spy, Key (PriK C)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Owner n, ⦃Num 3, Key (PubK C)⦄) ∈ s"
    hence "(Owner n, ⦃Num 3, PubKey C⦄) ∈ s" by simp
    ultimately show False
      by (rule asset_i_owner_iii [OF A])
  next
    fix A
    assume "(Spy, C ⊗ A) ∈ s"
    hence "C ⊗ A ∈ parts (used s)" by blast
    hence "(∃m. C = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey A⦄) ∈ s) ∨
      {PriKey C, PriKey A} ⊆ spied s"
      (is "(∃m. ?P m ∧ _) ∨ _")
      by (rule parts_mult [OF A])
    moreover assume "(Spy, Key (PriK C)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Owner n, ⦃Num 3, Key (PubK C)⦄) ∈ s"
    ultimately have "(Owner n, ⦃Num 3, Auth_PubKey m⦄) ∈ s" by simp
    thus False
      by (rule auth_pubkey_owner_iii [OF A])
  next
    fix A
    assume "(Spy, A ⊗ C) ∈ s"
    hence "A ⊗ C ∈ parts (used s)" by blast
    hence "(∃m. A = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey C⦄) ∈ s) ∨
      {PriKey A, PriKey C} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_mult [OF A])
    moreover assume "(Spy, Key (PriK C)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Owner n, ⦃Num 3, Key (PubK C)⦄) ∈ s"
    hence "(Owner n, ⦃Num 3, PubKey C⦄) ∈ s" by simp
    ultimately show False
      by (rule asset_ii_owner_iii [OF A])
  next
    fix Y
    assume "(Spy, ⦃Key (PriK C), Y⦄) ∈ s"
    hence "⦃PriKey C, Y⦄ ∈ parts (used s)" by auto
    hence "{PriKey C, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK C"], simp)
    moreover assume "(Spy, Key (PriK C)) ∉ s"
    ultimately show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (PriK C)⦄) ∈ s"
    hence "⦃X, PriKey C⦄ ∈ parts (used s)" by auto
    hence "{X, PriKey C} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK C"], simp add: image_def)
    moreover assume "(Spy, Key (PriK C)) ∉ s"
    ultimately show False by simp
  qed
qed

proposition asset_iii_secret [rule_format]:
 "s0 ⊨ s ⟹
    (Asset n, ⦃Num 4, PubKey D⦄) ∈ s ⟶
  PriKey D ∉ spied s"
proof (erule rtrancl_induct, simp add: image_def, rule impI)
  fix s s'
  assume
    A: "s0 ⊨ s" and
    B: "s ⊢ s'" and
    C: "(Asset n, ⦃Num 4, PubKey D⦄) ∈ s ⟶ PriKey D ∉ spied s" and
    D: "(Asset n, ⦃Num 4, PubKey D⦄) ∈ s'"
  show "PriKey D ∉ spied s'"
  proof (insert B C D, auto simp add: rel_def)
    assume "(Asset n, ⦃Num 4, Key (PubK D)⦄) ∈ s"
    hence "(Asset n, ⦃Num 4, PubKey D⦄) ∈ s" by simp
    hence "PriKey D ∈ used s"
      by (rule asset_iii_used [OF A, THEN mp])
    moreover assume "Key (PriK D) ∉ used s"
    ultimately show False by simp
  next
    fix K
    assume "(Spy, Crypt K (Key (PriK D))) ∈ s"
    hence "Crypt K (PriKey D) ∈ parts (used s)" by auto
    hence "(∃m. K = Auth_ShaKey m ∧
      (Asset m, Crypt (Auth_ShaKey m) (PriKey D)) ∈ s) ∨
      {PriKey D, Key K} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_crypt_prikey [OF A])
    moreover assume "(Spy, Key (PriK D)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Asset n, ⦃Num 4, Key (PubK D)⦄) ∈ s"
    hence "(Asset n, ⦃Num 4, PubKey D⦄) ∈ s" by simp
    ultimately show False
      by (rule asset_i_asset_iii [OF A])
  next
    fix A
    assume "(Spy, D ⊗ A) ∈ s"
    hence "D ⊗ A ∈ parts (used s)" by blast
    hence "(∃m. D = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey A⦄) ∈ s) ∨
      {PriKey D, PriKey A} ⊆ spied s"
      (is "(∃m. ?P m ∧ _) ∨ _")
      by (rule parts_mult [OF A])
    moreover assume "(Spy, Key (PriK D)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Asset n, ⦃Num 4, Key (PubK D)⦄) ∈ s"
    ultimately have "(Asset n, ⦃Num 4, Auth_PubKey m⦄) ∈ s" by simp
    thus False
      by (rule auth_pubkey_asset_iii [OF A])
  next
    fix A
    assume "(Spy, A ⊗ D) ∈ s"
    hence "A ⊗ D ∈ parts (used s)" by blast
    hence "(∃m. A = Auth_PriK m ∧ (Asset m, ⦃Num 2, PubKey D⦄) ∈ s) ∨
      {PriKey A, PriKey D} ⊆ spied s"
      (is "(∃m. _ ∧ ?P m) ∨ _")
      by (rule parts_mult [OF A])
    moreover assume "(Spy, Key (PriK D)) ∉ s"
    ultimately obtain m where "?P m" by auto
    moreover assume "(Asset n, ⦃Num 4, Key (PubK D)⦄) ∈ s"
    hence "(Asset n, ⦃Num 4, PubKey D⦄) ∈ s" by simp
    ultimately show False
      by (rule asset_ii_asset_iii [OF A])
  next
    fix Y
    assume "(Spy, ⦃Key (PriK D), Y⦄) ∈ s"
    hence "⦃PriKey D, Y⦄ ∈ parts (used s)" by auto
    hence "{PriKey D, Y} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK D"], simp)
    moreover assume "(Spy, Key (PriK D)) ∉ s"
    ultimately show False by simp
  next
    fix X
    assume "(Spy, ⦃X, Key (PriK D)⦄) ∈ s"
    hence "⦃X, PriKey D⦄ ∈ parts (used s)" by auto
    hence "{X, PriKey D} ⊆ spied s"
      by (rule parts_mpair_key [OF A, where K = "PriK D"], simp add: image_def)
    moreover assume "(Spy, Key (PriK D)) ∉ s"
    ultimately show False by simp
  qed
qed


theorem seskey_forward_secret:
  assumes
    A: "s0 ⊨ s" and
    B: "(Owner m, Crypt (SesK SK) (Pwd m)) ∈ s" and
    C: "(Asset n, Crypt (SesK SK) (Num 0)) ∈ s"
  shows "m = n ∧ SesKey SK ∉ spied s"
proof -
  have "(Owner m, SesKey SK) ∈ s"
    using A and B by (drule_tac owner_v_state, auto)
  with A have "∃C D. snd (snd SK) = {C, D} ∧
    (Owner m, ⦃Num 3, PubKey C⦄) ∈ s"
    by (drule_tac owner_seskey_other, auto)
  then obtain C D where
    D: "snd (snd SK) = {C, D} ∧ (Owner m, ⦃Num 3, PubKey C⦄) ∈ s"
    by blast
  with A have "PriKey C ∉ spied s"
    by (erule_tac owner_iii_secret, simp)
  moreover have "(Asset n, SesKey SK) ∈ s"
    using A and C by (drule_tac asset_v_state, auto)
  with A have "∃D. D ∈ snd (snd SK) ∧ (Asset n, ⦃Num 4, PubKey D⦄) ∈ s"
    by (drule_tac asset_seskey_other, auto)
  then obtain D' where
    E: "D' ∈ snd (snd SK) ∧ (Asset n, ⦃Num 4, PubKey D'⦄) ∈ s"
    by blast
  with A have "PriKey D' ∉ spied s"
    by (erule_tac asset_iii_secret, simp)
  moreover have "C ≠ D'"
    using A and D and E by (rule_tac notI, erule_tac asset_iii_owner_iii, auto)
  ultimately have "¬ (∃A. A ∈ snd (snd SK) ∧ PriKey A ∈ spied s)"
    using D and E by auto
  hence F: "SesKey SK ∉ spied s"
    using A by (rule_tac notI, drule_tac seskey_spied, auto)
  moreover have "Crypt (SesK SK) (Pwd n) ∈ used s"
    using A and C by (drule_tac asset_v_state, auto)
  hence "(∃SK'. SesK SK = SesK SK' ∧
    (Owner n, Crypt (SesK SK') (Pwd n)) ∈ s) ∨
    {Pwd n, Key (SesK SK)} ⊆ spied s"
    using A by (rule_tac parts_crypt_pwd, auto)
  ultimately have "(Owner n, Crypt (SesK SK) (Pwd n)) ∈ s"
    by simp
  with A and B have "m = n"
    by (rule owner_seskey_unique)
  thus ?thesis
    using F ..
qed

end