Added expand_parts_element macro
Lean Action CI / build (push) Has been cancelled

Further simplified proofs in NS_public
This commit is contained in:
Your Name
2026-03-04 18:44:21 +01:00
parent 7367681bc6
commit 58c093b18d
3 changed files with 176 additions and 229 deletions
+130 -201
View File
@@ -46,15 +46,6 @@ theorem possibility_property :
all_goals tauto
· simp
-- Lemmata for some very specific recurring cases in the following proof
omit [InvKey] [Bad] in
lemma Fake_parts_sing_helper {A B : Set Msg}
{ h : A B } :
X A h₁ X B h₁
:= by
intro h; cases h <;> try simp_all
left; aapply h
-- Spy never sees another agent's private key unless it's bad at the start
@[simp]
theorem Spy_see_priEK {h : ns_public evs} :
@@ -62,17 +53,14 @@ theorem Spy_see_priEK {h : ns_public evs} :
constructor
· induction h with
| Nil =>
simp[spies, knows, initState, pubEK, priEK, pubSK]; intro h
rcases h with (((B, bad, h | B, bad, h) | B, h) | B, h) <;>
try (apply injective_publicKey at h; simp_all)
all_goals (apply publicKey_neq_privateKey at h; contradiction)
simp[spies, knows, initState, pubEK, priEK, pubSK]
| Fake _ h ih =>
apply Fake_parts_sing at h
intro h₁; simp at h₁; apply Fake_parts_sing_helper (h := h) at h₁
simp at h₁; aapply ih;
| NS1 _ _ ih => simp; assumption
| NS2 _ _ _ ih => simp; assumption
| NS3 _ _ _ ih => simp; assumption
simp_all
| NS1 => simp_all
| NS2 => simp_all
| NS3 => simp_all
· intro h₁; apply parts_increasing; aapply Spy_spies_bad_privateKey
@[simp]
@@ -89,42 +77,30 @@ theorem no_nonce_NS1_NS2 { evs: List Event} { h : ns_public evs } :
Nonce NA analz (spies evs))) := by
intro h₁ h₂
induction h with
| Nil => rw[spies, knows] at h₂; simp[initState] at h₂
| Fake _ h ih =>
simp; apply analz_insert; right
| Nil => simp[spies, knows] at h₂
| Fake _ h ih =>
simp; apply analz_insert;
apply Fake_parts_sing at h
simp at h₁; apply Fake_parts_sing_helper (h := h) at h₁; simp at h₁
simp at h₂; apply Fake_parts_sing_helper (h := h) at h₂; simp at h₂
rcases h₁ with ((_ | _) | _) <;>
rcases h₁ with ((_ | _) | _) <;>
rcases h₂ with ((_ | _) | _) <;>
try simp_all
all_goals (aapply ih <;> aapply analz_subset_parts)
simp_all
all_goals (right; aapply ih <;> aapply analz_subset_parts)
| NS1 _ nonce_not_used =>
apply analz_spies_mono
simp [*] at *
apply parts_knows_Spy_subset_used_neg at nonce_not_used;
simp[spies] at h₁; rw[parts_element, Set.subset_def] at h₁; simp at h₁;
simp[spies] at h₂; rw[parts_element, Set.subset_def] at h₂; simp at h₂;
apply analz_mono; apply Set.subset_insert
expand_parts_element at h₁; expand_parts_element at h₂;
cases h₂ <;> simp_all
| NS2 _ nonce_not_used =>
apply analz_spies_mono
simp [*] at *
apply parts_knows_Spy_subset_used_neg at nonce_not_used;
simp[spies] at h; rw[parts_element, Set.subset_def] at h₁; simp at h₁;
simp[spies] at h₂; rw[parts_element, Set.subset_def] at h₂; simp at h₂;
apply analz_mono; apply Set.subset_insert
cases h₁ <;> simp_all
| NS3 _ _ _ a_ih => simp at h₁; simp at h₂; apply analz_mono
apply Set.subset_insert; aapply a_ih
expand_parts_element at h;
cases h₁ <;> simp_all[-Key.injEq]
| NS3 _ _ _ a_ih => apply analz_spies_mono; simp_all
@[simp]
lemma injective_pubEK_helper:
( pubEK A = pubEK B h) ( A = B h )
:= by
constructor
· intro h₁
rcases h₁ with e, _
apply injective_publicKey at e
aapply And.intro; simp_all
· intro h₁; simp_all
-- Unicity for NS1: nonce NA identifies agents A and B
theorem unique_NA { h : ns_public evs } :
(Crypt (pubEK B) Nonce NA, Agent A parts (spies evs)
@@ -132,36 +108,24 @@ theorem unique_NA { h : ns_public evs } :
(Nonce NA analz (spies evs)
A = A' B = B'))) := by
induction h with
| Nil => aesop (add norm spies, norm knows, safe analz_insertI)
| Nil => simp[spies, knows]
| Fake _ a a_ih =>
apply Fake_parts_sing at a; intro h₁ h₂ h₃;
simp[spies, knows] at h; apply Fake_parts_sing_helper (h := a) at h₁
simp at h₁
simp[spies, knows] at h₂; apply Fake_parts_sing_helper (h := a) at h
simp at h₂
simp[spies, knows] at h₃;
rcases h₁ with ((_ | _) | _) <;>
rcases h₂ with ((_ | _) | _) <;>
try (
apply False.elim; apply h₃; apply analz_mono; aapply Set.subset_insert
tauto
)
all_goals (aapply a_ih <;> try aapply analz_subset_parts
all_goals (
intro _; apply h₃; aapply analz_mono; aapply Set.subset_insert
))
apply analz_spies_mono_neg at h;
simp [*] at *
apply Fake_parts_sing_helper (h := a) at h
apply Fake_parts_sing_helper (h := a) at h₂
simp_all
| NS1 _ nonce_not_used a_ih =>
intro h₁ h₂ h₃
simp at h₁; rw[parts_element, Set.subset_def] at h₁; simp at h
simp at h₂; rw[parts_element, Set.subset_def] at h₂; simp at h₂
apply analz_insert_mono_neg at h
simp [*] at *
expand_parts_element at h₁
expand_parts_element at h₂
apply parts_knows_Spy_subset_used_neg at nonce_not_used
cases h₁ <;> cases h₂ <;> simp_all
aapply a_ih; intro h; apply h₃; apply_rules[analz_mono, Set.subset_insert]
| NS2 _ _ _ a_ih => intro h₁ h₂ h₃; simp_all; apply a_ih; intro h; apply h₃
apply_rules [analz_mono, Set.subset_insert]
| NS3 _ _ _ a_ih => intro h₁ h₂ h₃; simp at h₁; simp at h₂; aapply a_ih
intro h; apply h₃
apply_rules [analz_mono, Set.subset_insert]
| NS2 => intro _ _ h₃; apply analz_insert_mono_neg at h₃; simp_all
| NS3 => intro _ _ h₃; apply analz_insert_mono_neg at h₃; simp_all;
-- Spy does not see the nonce sent in NS1 if A and B are secure
theorem Spy_not_see_NA { h : ns_public evs }
@@ -172,7 +136,7 @@ theorem Spy_not_see_NA { h : ns_public evs }
intro h₁ h₄
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
| Fake _ a =>
have _ := Spy_in_bad; apply Fake_analz_insert at a; apply a at h₄; simp_all
| NS1 _ a a_ih => simp_all; cases h₁ with
| inl => simp_all; apply a; aapply analz_knows_Spy_subset_used
@@ -180,38 +144,28 @@ theorem Spy_not_see_NA { h : ns_public evs }
· simp_all; apply Says_imp_used at h
apply used_parts_subset_parts at h; apply a; apply h; simp
· aapply a_ih
| NS2 _ not_used_NB a a_ih =>
cases h₁ with | tail _ b =>
have _ := h₄
simp at h₄; apply analz_insert_Crypt_subset at h₄
simp at h₄; rcases h₄ with ( h | h | h)
· simp at a_ih; have c := b; apply a_ih at c; rw[h] at b;
have _ := c; rw[h] at c;
apply Says_imp_parts_knows_Spy at b
apply Says_imp_parts_knows_Spy at a
apply unique_NA at b; apply b at a; apply a at c; simp_all
assumption
· rw [h] at b
apply not_used_NB; apply parts_knows_Spy_subset_used; apply parts.fst;
apply parts.body; apply Says_imp_parts_knows_Spy; assumption
· aapply a_ih
| NS3 _ a₁ a₂ a_ih =>
cases h₁ with | tail _ b =>
have _ := h₄
simp at h; apply analz_insert_Crypt_subset at h
simp at h₄; rcases h₄ with ( h | h | h)
· have _ := b; have _ := a₁; have _ := a₂
rw[h] at b; apply Says_imp_parts_knows_Spy at b
apply Says_imp_parts_knows_Spy at a₂
aapply a_ih; apply no_nonce_NS1_NS2
· assumption
· rw[h]; exact a₂
· rw[h]; exact b
· aapply a_ih; aapply analz.inj
· aapply a_ih; aapply analz.fst
· aapply a_ih; aapply analz.snd
· aapply a_ih; aapply analz.decrypt
| NS2 _ not_used_NB a a_ih =>
simp at h₁
have _ := h₄
simp at h₄; apply analz_insert_Crypt_subset at h₄
simp at h₄; rcases h₄ with ( h | h | h)
· simp [*] at *; have c := h₁; apply a_ih at c;
have _ := c;
apply Says_imp_parts_knows_Spy at h₁
apply Says_imp_parts_knows_Spy at a
apply unique_NA at h₁; apply h₁ at a; apply a at c; all_goals simp_all
· simp_all
apply not_used_NB; apply parts_knows_Spy_subset_used; apply parts.fst;
apply parts.body; apply Says_imp_parts_knows_Spy; assumption
· aapply a_ih
| NS3 _ _ a₂ a_ih =>
simp [*] at *
have _ := h₄
apply analz_insert_Crypt_subset at h₄; simp[*] at h₄;
have _ := h₁; simp[*] at h; apply Says_imp_parts_knows_Spy at h
apply Says_imp_parts_knows_Spy at a₂
aapply a_ih; apply no_nonce_NS1_NS2 <;> try simp [*] <;> assumption
-- Authentication for `A`: if she receives message 2 and has used `NA` to start a run, then `B` has sent message 2.
theorem A_trusts_NS2 {h : ns_public evs }
{ not_bad_A : A bad }
@@ -225,36 +179,29 @@ theorem A_trusts_NS2 {h : ns_public evs }
-- use unique_NA to show that B' = B
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
| Fake _ a a_ih =>
have snsNA := h₁; apply Spy_not_see_NA at snsNA <;> try assumption
simp at h₁; simp at h₂;
apply analz_spies_mono_neg at snsNA
simp [*] at *
cases h₁
· have _ := Spy_in_bad; simp_all
· right; apply Fake_parts_sing at a;
· apply Fake_parts_sing at a;
apply Fake_parts_sing_helper (h := a) at h₂; simp at h₂
rcases h₂ with ((_ | _) | _) <;> aapply a_ih
rcases h₂ with ((_ | _) | _) <;> (right; aapply a_ih)
· aapply analz_subset_parts
· apply False.elim; apply snsNA; apply analz_spies_mono; tauto;
· tauto
· aapply ns_public.Fake
| NS1 _ a a_ih => right; simp at h₂; cases h₁
· apply False.elim; apply a
apply parts_knows_Spy_subset_used; apply parts.fst
aapply parts.body
· aapply a_ih;
| NS1 _ a a_ih =>
apply parts_knows_Spy_subset_used_neg at a;
simp [*] at *; expand_parts_element at h₂; cases h₁ <;> simp_all
| NS2 _ _ a a_ih =>
simp at h₁; have b := h₁; have snsNA := h₁
apply Spy_not_see_NA at snsNA <;> try assumption
simp at h₂; rcases h₂ with (_ , e₂ , _, e₄ | _)
· apply Says_imp_parts_knows_Spy at a
apply Says_imp_parts_knows_Spy at b
apply unique_NA at a
rw[e₂] at b; rw[e₂] at snsNA
apply a at b
apply b at snsNA
simp_all[-e₄]; assumption
· right; aapply a_ih
| NS3 _ _ a a_ih => simp at h₁; simp at h₂; right; aapply a_ih
simp [*] at *
have snsNA := h₁; apply Spy_not_see_NA at snsNA <;> try assumption
cases h₂ <;> simp_all
apply Says_imp_parts_knows_Spy at a; apply unique_NA at a;
apply Says_imp_parts_knows_Spy at h₁; apply a at h₁; all_goals simp_all
| NS3 _ _ a a_ih => simp_all;
-- If the encrypted message appears then it originated with Alice in `NS1`
lemma B_trusts_NS1 { h : ns_public evs} :
Crypt (pubEK B) Nonce NA, Agent A parts (spies evs)
@@ -263,20 +210,16 @@ lemma B_trusts_NS1 { h : ns_public evs} :
:= by
intro h₁ h₂
induction h with
| Nil => simp[spies] at h₁; rw[knows] at h₁; simp[initState] at h₁
| Nil => simp[spies, knows] at h₁
| Fake _ a a_ih =>
apply analz_spies_mono_neg at h₂
simp at h₁; apply Fake_parts_sing at a;
apply Fake_parts_sing_helper (h := a) at h₁; simp at h₁
rcases h₁ with ((h₁ | h₁ )| h₁);
· right; aapply a_ih; aapply analz_subset_parts; aapply analz_spies_mono_neg
· apply False.elim; apply h₂; apply analz_spies_mono; simp_all
· right; aapply a_ih; aapply analz_spies_mono_neg
| NS1 _ _ a_ih => simp at h₁; cases h₁
· simp_all
· right; aapply a_ih; aapply analz_spies_mono_neg
| NS2 _ _ _ a_ih => simp at h₁; right; aapply a_ih; aapply analz_spies_mono_neg
| NS3 _ _ _ a_ih => simp at h₁; right; aapply a_ih; aapply analz_spies_mono_neg
apply Fake_parts_sing_helper (h := a) at h₁; simp_all
| NS1 _ _ a_ih =>
apply analz_spies_mono_neg at h₂; simp_all; cases h₁ <;> simp_all
| NS2 _ _ _ a_ih => apply analz_spies_mono_neg at h₂; simp_all;
| NS3 _ _ _ a_ih => apply analz_spies_mono_neg at h₂; simp_all;
-- Authenticity Properties obtained from `NS2`
-- Unicity for `NS2`: nonce `NB` identifies nonce `NA` and agent `A`
@@ -289,33 +232,28 @@ theorem unique_NB { h : ns_public evs } :
induction h with
| Nil => aesop (add norm spies, norm knows, safe analz_insertI)
| Fake _ a a_ih =>
intro h₁ h₂ h₃;
apply Fake_parts_sing at a
simp[spies, knows] at h₁; apply Fake_parts_sing_helper (h := a) at h
simp at h;
simp at h₂; apply Fake_parts_sing_helper (h := a) at h₂; simp at h₂;
apply analz_spies_mono_neg at h₃
rcases h₁ with ((h₁ | h₁) | h₁) <;>
rcases h₂ with ((h₂ | h₂) | h₂) <;>
apply Fake_parts_sing at a; intro h₁ h₂ h₃; simp [*] at *
apply Fake_parts_sing_helper (h := a) at h₁;
apply Fake_parts_sing_helper (h := a) at h; simp [*] at *
apply analz_insert_mono_neg at h
rcases h₁ with ((_ | _) | _) <;>
rcases h₂ with ((_ | _) | _) <;>
simp_all
all_goals (aapply a_ih; repeat aapply analz_subset_parts)
| NS1 _ _ a_ih => intro h₁ h₂ h₃; simp at h₁; simp at h₂; aapply a_ih
aapply analz_spies_mono_neg
| NS2 _ nonce_not_used _ a_ih =>
intro h₁ h₂ h₃;
-- This is how to rewrite `M ∈ parts` terms into something useful
-- TODO create a macro for this
-- TODO this should work with analz as well
simp at h₁; rw[parts_element, Set.subset_def] at h₁; simp at h₁
simp at h₂; rw[parts_element, Set.subset_def] at h₂; simp at h₂
apply analz_spies_mono_neg at h₃;
intro h₁ h₂ h₃; simp [*] at *
expand_parts_element at h₁
expand_parts_element at h₂
apply analz_insert_mono_neg at h₃;
apply parts_knows_Spy_subset_used_neg at nonce_not_used
rcases h₁ with (_ | h₁) <;>
rcases h₂ with (_ | h₂) <;> simp_all
| NS3 _ _ _ a_ih =>
intro h₁ h₂ h₃; apply analz_spies_mono_neg at h₃; simp_all;
intro h₁ h₂ h₃; apply analz_spies_mono_neg at h₃; simp_all[-Key.injEq]
-- `NB` remains secret
-- `NB` remains secret
theorem Spy_not_see_NB { h : ns_public evs }
{ not_bad_A : A bad }
{ not_bad_B : B bad } :
@@ -328,73 +266,66 @@ theorem Spy_not_see_NB { h : ns_public evs }
| Fake _ a a_ih =>
have _ := Spy_in_bad; apply Fake_analz_insert at a; apply a at h₄; simp_all;
| NS1 _ nonce_not_used a_ih =>
simp at h₁
simp[spies, knows] at h₄; apply analz_insert_Crypt_subset at h₄; simp at h₄
simp [*] at *
apply analz_insert_Crypt_subset at h₄; simp at h₄
apply parts_knows_Spy_subset_used_neg at nonce_not_used
cases h with
| inl e => apply Says_imp_parts_knows_Spy at h;
rw[parts_element, Set.subset_def] at h₁; simp_all
| inr => aapply a_ih
have h := h₁; apply Says_imp_parts_knows_Spy at h₂
expand_parts_element at h; simp_all
| NS2 _ not_used_NB a a_ih =>
simp at h₁;
simp[spies, knows] at h₄;
simp [*] at *
apply parts_knows_Spy_subset_used_neg at not_used_NB
rcases h₁ with (_ | h₁)
· simp_all; apply not_used_NB; aapply analz_subset_parts
· apply analz_insert_Crypt_subset at h₄; simp at h₄; rcases h₄ with (_ |_ |_ )
· aapply a_ih; apply Says_imp_parts_knows_Spy at a;
· aapply a_ih; apply Says_imp_parts_knows_Spy at a;
apply Says_imp_parts_knows_Spy at h₁; simp_all; aapply no_nonce_NS1_NS2
· apply Says_imp_parts_knows_Spy at h₁;
rw[parts_element, Set.subset_def] at h₁; simp_all
expand_parts_element at h₁; simp_all
· aapply a_ih
| NS3 _ _ a a_ih =>
simp at h₁; simp[analz_insert_Crypt_element] at h₄;
simp at h₁; simp[analz_insert_Crypt_element] at h₄;
rcases h₄ with (_, _ | _, _) <;> simp_all
apply Says_imp_parts_knows_Spy at a
apply Says_imp_parts_knows_Spy at h₁; apply unique_NB at a
apply a at h₁; apply h₁ at a_ih; simp_all; assumption
-- Authentication for `B`: if he receives message 3 and has used `NB` in message 2, then `A` has sent message 3.
theorem B_trusts_NS3 { h : ns_public evs }
theorem B_trusts_NS3 { h : ns_public evs }
{ not_bad_A : A bad }
{ not_bad_B : B bad } :
Says B A (Crypt (pubEK A) Nonce NA, Nonce NB, Agent B) evs
Says A' B (Crypt (pubEK B) (Nonce NB)) evs
Says A B (Crypt (pubEK B) (Nonce NB)) evs
:= by
:= by
intro h₁ h₂
apply Says_imp_parts_knows_Spy at h₂
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
right; simp at h₁
simp [*] at *
apply Fake_parts_sing at a
simp at h₂; apply Fake_parts_sing_helper (h := a) at h₂; simp at h₂
rw[parts_element, Set.subset_def] at h₂; simp at h₂
have _ := Spy_in_bad
rcases h with (h₁ | h₁) <;> rcases h with ((h₂ | h₂) | h₂) <;> simp_all
· aapply a_ih; aapply analz_subset_parts
apply Fake_parts_sing_helper (h := a) at h₂; simp at h₂
expand_parts_element at h₂;
rcases h₁ with (_ | h₁) <;>
rcases h₂ with ((h₂ | _) | _) <;> simp_all[Spy_in_bad]
· apply analz_subset_parts at h₂; simp_all
· apply Spy_not_see_NB at h₁ <;> simp_all
· aapply a_ih
| NS1 _ a a_ih => right; simp at h₂; simp at h₁; aapply a_ih;
| NS2 _ nonce_not_used a a_ih =>
right
| NS1 => simp_all
| NS2 _ nonce_not_used =>
simp [*] at *
apply parts_knows_Spy_subset_used_neg at nonce_not_used;
simp at h₂; rw[parts_element, Set.subset_def] at h₂; simp at h₂
simp at h₁; cases h₁ <;> simp_all; aapply a_ih
| NS3 _ _ a₂ a_ih =>
simp at h
simp at h₂; rw[parts_element, Set.subset_def] at h₂; simp at h₂
cases h₂ <;> simp_all
expand_parts_element at h₂; cases h₁ <;> simp_all
| NS3 _ _ a₂ =>
simp [*] at *;
expand_parts_element at h; cases h₂ <;> simp_all
have h₁c := h₁
apply Spy_not_see_NB at h₁c
apply Says_imp_parts_knows_Spy at h₁
apply Says_imp_parts_knows_Spy at a₂
apply unique_NB at h₁; apply h₁ at a₂
apply a₂ at h₁c; all_goals simp_all
apply Says_imp_parts_knows_Spy at h₁; apply unique_NB at h₁;
apply Says_imp_parts_knows_Spy at a₂; apply h₁ at a₂
all_goals simp_all
-- Overall guarantee for `B`
-- If NS3 has been sent and the nonce NB agrees with the nonce B joined with NA, then A initiated the run using NA
theorem B_trusts_protocol { h : ns_public evs }
{ not_bad_A : A bad }
@@ -406,24 +337,22 @@ theorem B_trusts_protocol { h : ns_public evs }
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
right
simp [*] at *
apply Fake_parts_sing at a
simp at h₁; apply Fake_parts_sing_helper (h := a) at h₁;
rw[parts_element, Set.subset_def] at h₁; simp at h₁
have _ := Spy_in_bad
simp at h₂; rcases h₂ with (_ | h₂) <;> simp_all
rcases h₁ with (((_ |_ ) | _) | _) <;> try (aapply a_ih)
· aapply analz_subset_parts
apply Fake_parts_sing_helper (h := a) at h₁;
expand_parts_element at h₁
rcases h₂ with (_ | h₂) <;> simp_all[Spy_in_bad]
rcases h₁ with (((_ |_ ) | _) | _) <;> try simp_all
· right; aapply a_ih; aapply analz_subset_parts
· apply Spy_not_see_NB at h₂ <;> simp_all
· simp_all
| NS1 _ a a_ih => right; simp at h₂; simp at h₁; aapply a_ih;
| NS2 _ _ a a_ih => right; simp at h₁; simp at h₂; cases h₂ with
| inl => apply parts.body at h₁; apply parts_knows_Spy_subset_used at h₁
simp_all
| inr => aapply a_ih
| NS1 => simp_all
| NS2 _ nonce_not_used a a_ih =>
simp [*] at *
apply parts_knows_Spy_subset_used_neg at nonce_not_used;
expand_parts_element at h₁; cases h₂ <;> simp_all
| NS3 _ _ a₂ a_ih =>
simp at h₂
simp at h₁; rw[parts_element, Set.subset_def] at h₁; simp at h₁
simp [*] at *
expand_parts_element at h₁
cases h₁ <;> simp_all
have h₂c := h₂
apply Spy_not_see_NB at h₂c