(* Title: HOL/SET_Protocol/Public_SET.thy Author: Giampaolo Bella Author: Fabio Massacci Author: Lawrence C Paulson *)
section‹The Public-Key Theory, Modified for SET›
theory Public_SET imports Event_SET begin
subsection‹Symmetric and Asymmetric Keys›
text‹definitions influenced by the wish to assign asymmetric keys - since the beginning - only to RCA and CAs, namely we need a partial function on type Agent›
text‹The SET specs mention two signature keys for CAs - we only have one›
consts
publicKey :: "[bool, agent] ==> key" 🍋‹the boolean is TRUE if a signing key›
(*BEWARE!! priEK, priSK DON'T WORK with inj, range, image, etc.*) abbreviation"priEK A == invKey (pubEK A)" abbreviation"priSK A == invKey (pubSK A)"
text‹By freeness of agents, no two agents have the same key. Since 🍋‹True≠False›,
specification (publicKey)
injective_publicKey: "publicKey b A = publicKey c A' ==> b=c ∧ A=A'" (*<*) apply (rule exI [of _ "%b A. 2 * nat_of_agent A + (if b then 1 else 0)"]) apply (auto simp add: inj_on_def inj_nat_of_agent [THEN inj_eq] split: agent.split) apply (drule_tac f="%x. x mod 2"in arg_cong, simp add: mod_Suc)+ (*or this, but presburger won't abstract out the function applications apply presburger+ *) done (*>*)
axiomatizationwhere (*No private key equals any public key (essential to ensure that private keys are private!) *)
privateKey_neq_publicKey [iff]: "invKey (publicKey b A) ≠ publicKey b' A'"
text‹This information is not necessary. Each protocol distributes any needed certificates, and anyway our proofs require a formalization of the Spy's knowledge only. However, the initial knowledge is as follows: All agents know RCA's public keys; RCA and CAs know their own respective keys; RCA (has already certified and therefore) knows all CAs public keys; Spy knows all keys of all bad agents.›
overloading initState ≡"initState" begin
primrec initState where (*<*)
initState_CA: "initState (CA i) = (if i=0 then Key ` ({priEK RCA, priSK RCA} ∪ pubEK ` (range CA) ∪ pubSK ` (range CA)) else {Key (priEK (CA i)), Key (priSK (CA i)), Key (pubEK (CA i)), Key (pubSK (CA i)), Key (pubEK RCA), Key (pubSK RCA)})"
text‹Injective mapping from agents to PANs: an agent can have only one card›
consts pan :: "agent ==> nat"
specification (pan)
inj_pan: "inj pan" 🍋‹No two agents have the same PAN› (*<*) apply (rule exI [of _ "nat_of_agent"]) apply (simp add: inj_on_def inj_nat_of_agent [THEN inj_eq]) done (*>*)
declare inj_pan [THEN inj_eq, iff]
consts
XOR :: "nat*nat ==> nat"🍋‹no properties are assumed of exclusive-or›
subsection‹Signature Primitives›
definition (* Signature = Message + signed Digest *)
sign :: "[key, msg]==>msg" where"sign K X = {X, Crypt K (Hash X) }"
definition (* Signature Only = signed Digest Only *)
signOnly :: "[key, msg]==>msg" where"signOnly K X = Crypt K (Hash X)"
definition (* Signature for Certificates = Message + signed Message *)
signCert :: "[key, msg]==>msg" where"signCert K X = {X, Crypt K X }"
definition (* Certification Authority's Certificate. Contains agent name, a key, a number specifying the key's target use, a key to sign the entire certificate. Should prove if signK=priSK RCA and C=CA i, then Ka=pubEK i or pubSK i depending on T ?? *)
cert :: "[agent, key, msg, key] ==> msg" where"cert A Ka T signK = signCert signK {Agent A, Key Ka, T}"
definition (* Cardholder's Certificate. Contains a PAN, the certified key Ka, the PANSecret PS, a number specifying the target use for Ka, the signing key signK. *)
certC :: "[nat, key, nat, msg, key] ==> msg" where"certC PAN Ka PS T signK = signCert signK {Hash {Nonce PS, Pan PAN}, Key Ka, T}"
(*cert and certA have no repeated elements, so they could be abbreviations, but that's tricky and makes proofs slower*)
abbreviation"onlyEnc == Number 0" abbreviation"onlySig == Number (Suc 0)" abbreviation"authCode == Number (Suc (Suc 0))"
subsection‹Encryption Primitives›
definition EXcrypt :: "[key,key,msg,msg] ==> msg"where 🍋‹Extra Encryption› (*K: the symmetric key EK: the public encryption key*) "EXcrypt K EK M m = {Crypt K {M, Hash m}, Crypt EK {Key K, m}}"
definition EXHcrypt :: "[key,key,msg,msg] ==> msg"where 🍋‹Extra Encryption with Hashing› (*K: the symmetric key EK: the public encryption key*) "EXHcrypt K EK M m = {Crypt K {M, Hash m}, Crypt EK {Key K, m, Hash M}}"
definition Enc :: "[key,key,key,msg] ==> msg"where 🍋‹Simple Encapsulation with SIGNATURE› (*SK: the sender's signing key K: the symmetric key EK: the public encryption key*) "Enc SK K EK M = {Crypt K (sign SK M), Crypt EK (Key K)}"
definition EncB :: "[key,key,key,msg,msg] ==> msg"where 🍋‹Encapsulation with Baggage. Keys as above, and baggage b.› "EncB SK K EK M b = {Enc SK K EK {M, Hash b}, b}"
subsection‹Basic Properties of pubEK, pubSK, priEK and priSK›
lemma publicKey_eq_iff [iff]: "(publicKey b A = publicKey b' A') = (b=b' ∧ A=A')" by (blast dest: injective_publicKey)
lemma privateKey_eq_iff [iff]: "(invKey (publicKey b A) = invKey (publicKey b' A')) = (b=b' ∧ A=A')" by auto
lemma not_symKeys_publicKey [iff]: "publicKey b A ∉ symKeys" by (simp add: symKeys_def)
lemma not_symKeys_privateKey [iff]: "invKey (publicKey b A) ∉ symKeys" by (simp add: symKeys_def)
lemma symKeys_invKey_eq [simp]: "K ∈ symKeys ==> invKey K = K" by (simp add: symKeys_def)
lemma symKeys_invKey_iff [simp]: "(invKey K ∈ symKeys) = (K ∈ symKeys)" by (unfold symKeys_def, auto)
text‹Can be slow (or even loop) as a simprule› lemma symKeys_neq_imp_neq: "(K ∈ symKeys) ≠ (K' ∈ symKeys) ==> K ≠ K'" by blast
text‹These alternatives to ‹symKeys_neq_imp_neq›don't seem any better in practice.› lemma publicKey_neq_symKey: "K ∈ symKeys ==> publicKey b A ≠ K" by blast
lemma symKey_neq_publicKey: "K ∈ symKeys ==> K ≠ publicKey b A" by blast
lemma privateKey_neq_symKey: "K ∈ symKeys ==> invKey (publicKey b A) ≠ K" by blast
lemma symKey_neq_privateKey: "K ∈ symKeys ==> K ≠ invKey (publicKey b A)" by blast
lemma analz_symKeys_Decrypt: "[| Crypt K X ∈ analz H; K ∈ symKeys; Key K ∈ analz H |] ==> X ∈ analz H" by auto
subsection‹"Image" Equations That Hold for Injective Functions›
lemma invKey_image_eq [iff]: "(invKey x ∈ invKey`A) = (x∈A)" by auto
text‹holds because invKey is injective› lemma publicKey_image_eq [iff]: "(publicKey b A ∈ publicKey c ` AS) = (b=c ∧ A∈AS)" by auto
lemma privateKey_image_eq [iff]: "(invKey (publicKey b A) ∈ invKey ` publicKey c ` AS) = (b=c ∧ A∈AS)" by auto
lemma privateKey_notin_image_publicKey [iff]: "invKey (publicKey b A) ∉ publicKey c ` AS" by auto
lemma publicKey_notin_image_privateKey [iff]: "publicKey b A ∉ invKey ` publicKey c ` AS" by auto
text‹Spy sees private keys of bad agents! [and obviously public keys too]› lemma knows_Spy_bad_privateKey [intro!]: "A ∈ bad ==> Key (invKey (publicKey b A)) ∈ knows Spy evs" by (rule initState_subset_knows [THEN subsetD], simp)
subsection‹Fresh Nonces for Possibility Theorems›
lemma Nonce_notin_initState [iff]: "Nonce N ∉ parts (initState B)" by (induct_tac "B", auto)
lemma Nonce_notin_used_empty [simp]: "Nonce N ∉ used []" by (simp add: used_Nil)
text‹In any trace, there is an upper bound N on the greatest nonce in use.› lemma Nonce_supply_lemma: "∃N. ∀n. N≤n ⟶ Nonce n ∉ used evs" apply (induct_tac "evs") apply (rule_tac x = 0 in exI) apply (simp_all add: used_Cons split: event.split, safe) apply (rule msg_Nonce_supply [THEN exE], blast elim!: add_leE)+ done
lemma Nonce_supply1: "∃N. Nonce N ∉ used evs" by (rule Nonce_supply_lemma [THEN exE], blast)
lemma Nonce_supply: "Nonce (SOME N. Nonce N ∉ used evs) ∉ used evs" apply (rule Nonce_supply_lemma [THEN exE]) apply (rule someI, fast) done
subsection‹Specialized Methods for Possibility Theorems›
ML ‹ (*Tactic for possibility theorems*) fun possibility_tac ctxt =
REPEAT (*omit used_Says so that Nonces start from different traces!*)
(ALLGOALS (simp_tac (ctxt delsimps [@{thm used_Says}, @{thm used_Notes}])) THEN
REPEAT_FIRST (eq_assume_tac ORELSE'
resolve_tac ctxt [refl, conjI, @{thm Nonce_supply}]))
(*For harder protocols (such as SET_CR!), where we have to set up some nonces and keys initially*) fun basic_possibility_tac ctxt =
REPEAT
(ALLGOALS (asm_simp_tac (ctxt |> Simplifier.set_unsafe_solver safe_solver)) THEN
REPEAT_FIRST (resolve_tac ctxt [refl, conjI])) ›
subsection‹Specialized Rewriting for Theorems About 🍋‹analz› and Image›
lemma insert_Key_singleton: "insert (Key K) H = Key ` {K} ∪ H" by blast
lemma insert_Key_image: "insert (Key K) (Key`KK ∪ C) = Key ` (insert K KK) ∪ C" by blast
text‹Needed for ‹DK_fresh_not_KeyCryptKey›\lemma publicKey_in_used [iff]: "Key (publicKey b A) ∈ used evs" by auto
lemma privateKey_in_used [iff]: "Key (invKey (publicKey b A)) ∈ used evs" by (blast intro!: initState_into_used)
text‹Reverse the normal simplification of "image" to build up (not break down) the set of keys. Based on ‹analz_image_freshK_ss›, but simpler.› lemmas analz_image_keys_simps =
simp_thms mem_simps 🍋‹these two allow its use with ‹only:›\›
image_insert [THEN sym] image_Un [THEN sym]
rangeI symKeys_neq_imp_neq
insert_Key_singleton insert_Key_image Un_assoc [THEN sym]
(*General lemmas proved by Larry*)
subsection‹Controlled Unfolding of Abbreviations›
text‹A set is expanded only if a relation is applied to it› lemma def_abbrev_simp_relation: "A = B ==> (A ∈ X) = (B ∈ X) ∧ (u = A) = (u = B) ∧ (A = u) = (B = u)" by auto
text‹A set is expanded only if one of the given functions is applied to it› lemma def_abbrev_simp_function: "A = B ==> parts (insert A X) = parts (insert B X) ∧ analz (insert A X) = analz (insert B X) ∧ keysFor (insert A X) = keysFor (insert B X)" by auto
subsubsection‹Special Simplification Rules for 🍋‹signCert›\ text‹Avoids duplicating X and its components!› lemma parts_insert_signCert: "parts (insert (signCert K X) H) = insert {X, Crypt K X} (parts (insert (Crypt K X) H))" by (simp add: signCert_def insert_commute [of X])
text‹Avoids a case split! [X is always available]› lemma analz_insert_signCert: "analz (insert (signCert K X) H) = insert {X, Crypt K X} (insert (Crypt K X) (analz (insert X H)))" by (simp add: signCert_def insert_commute [of X])
lemma keysFor_insert_signCert: "keysFor (insert (signCert K X) H) = keysFor H" by (simp add: signCert_def)
text‹Controlled rewrite rules for 🍋‹signCert›, just the definitions of the others. Encryption primitives are just expanded, despite their huge redundancy!› lemmas abbrev_simps [simp] =
parts_insert_signCert analz_insert_signCert keysFor_insert_signCert
sign_def [THEN def_abbrev_simp_relation]
sign_def [THEN def_abbrev_simp_function]
signCert_def [THEN def_abbrev_simp_relation]
signCert_def [THEN def_abbrev_simp_function]
certC_def [THEN def_abbrev_simp_relation]
certC_def [THEN def_abbrev_simp_function]
cert_def [THEN def_abbrev_simp_relation]
cert_def [THEN def_abbrev_simp_function]
EXcrypt_def [THEN def_abbrev_simp_relation]
EXcrypt_def [THEN def_abbrev_simp_function]
EXHcrypt_def [THEN def_abbrev_simp_relation]
EXHcrypt_def [THEN def_abbrev_simp_function]
Enc_def [THEN def_abbrev_simp_relation]
Enc_def [THEN def_abbrev_simp_function]
EncB_def [THEN def_abbrev_simp_relation]
EncB_def [THEN def_abbrev_simp_function]
subsubsection‹Elimination Rules for Controlled Rewriting›
lemma Enc_partsE: "!!R. [|Enc SK K EK M ∈ parts H; [|Crypt K (sign SK M) ∈ parts H; Crypt EK (Key K) ∈ parts H|] ==> R|] ==> R"
by (unfold Enc_def, blast)
lemma EncB_partsE: "!!R. [|EncB SK K EK M b ∈ parts H; [|Crypt K (sign SK {M, Hash b}) ∈ parts H; Crypt EK (Key K) ∈ parts H; b ∈ parts H|] ==> R|] ==> R" by (unfold EncB_def Enc_def, blast)
lemma EXcrypt_partsE: "!!R. [|EXcrypt K EK M m ∈ parts H; [|Crypt K {M, Hash m}∈ parts H; Crypt EK {Key K, m}∈ parts H|] ==> R|] ==> R" by (unfold EXcrypt_def, blast)
subsection‹Lemmas to Simplify Expressions Involving 🍋‹analz›\›
lemma analz_knows_absorb: "Key K ∈ analz (knows Spy evs) ==> analz (Key ` (insert K H) ∪ knows Spy evs) = analz (Key ` H ∪ knows Spy evs)" by (simp add: analz_insert_eq Un_upper2 [THEN analz_mono, THEN subsetD])
lemma analz_knows_absorb2: "Key K ∈ analz (knows Spy evs) ==> analz (Key ` (insert X (insert K H)) ∪ knows Spy evs) = analz (Key ` (insert X H) ∪ knows Spy evs)" apply (subst insert_commute) apply (erule analz_knows_absorb) done
lemma in_parts_Says_imp_used: "[|Key K ∈ parts {X}; Says A B X ∈ set evs|] ==> Key K ∈ used evs" by (blast intro: parts_trans dest!: Says_imp_knows_Spy [THEN parts.Inj])
text‹A useful rewrite rule with 🍋‹analz_image_keys_simps›\› lemma Crypt_notin_image_Key: "Crypt K X ∉ Key ` KK" by auto
lemma fresh_notin_analz_knows_Spy: "Key K ∉ used evs ==> Key K ∉ analz (knows Spy evs)" by (auto dest: analz_into_parts)
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet am 2026-04-26)
¤
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.