Finished proff of NS
Lean Action CI / build (push) Has been cancelled

This commit is contained in:
Your Name
2026-02-25 17:27:16 +01:00
parent 31e638dd90
commit 96e5d59603
3 changed files with 382 additions and 24 deletions
+15 -3
View File
@@ -185,10 +185,10 @@ lemma knows_Spy_partsEs [Bad] :
Event.Says A B X evs X parts (knows Agent.Spy evs) := by
exact Says_imp_parts_knows_Spy
lemma Says_imp_analz_Spy [InvKey] [Bad] :
{A B : Agent} {X : Msg} {evs : List Event},
lemma Says_imp_analz_Spy [InvKey] [Bad]
{A B : Agent} {X : Msg} {evs : List Event} :
Event.Says A B X evs X analz (knows Agent.Spy evs) := by
intro A B X evs h
intro h
apply analz.inj
apply Says_imp_knows_Spy
exact h
@@ -209,6 +209,18 @@ lemma parts_insert_spies [Bad] :
by
apply parts_insert
lemma analz_spies_mono [InvKey] [Bad]
{ h : M analz (knows Agent.Spy evs) } :
M analz (knows Agent.Spy (ev :: evs))
:= by
aapply analz_mono; exact knows_subset_knows_Cons
lemma analz_spies_mono_neg [InvKey] [Bad]
{ h : M analz (knows Agent.Spy (ev :: evs)) } :
M analz (knows Agent.Spy evs)
:= by
intro h₁; apply h; aapply analz_spies_mono
-- Knowledge of Agents
lemma knows_subset_knows_Says [Bad] :
{A A' B : Agent} {X : Msg} {evs : List Event},
-1
View File
@@ -911,7 +911,6 @@ by
lemma analz_subset_iff {G H : Set Msg} [InvKey] : (G analz H) (analz G analz H) :=
by apply analzClosureOperator.le_closure_iff
@[simp]
lemma analz_trans {G H : Set Msg} {X : Msg} [InvKey] :
X analz G G analz H X analz H :=
by
+367 -20
View File
@@ -108,7 +108,7 @@ lemma no_nonce_NS1_NS2_helper2
| inr => aapply h₁
-- It is impossible to re-use a nonce in both NS1 and NS2, provided the nonce is secret
theorem no_nonce_NS1_NS2 { h : ns_public evs } :
theorem no_nonce_NS1_NS2 { evs: List Event} { h : ns_public evs } {A B C D : Agent} :
(Crypt (pubEK C) NA', Nonce NA, Agent D parts (spies evs)
(Crypt (pubEK B) Nonce NA, Agent A parts (spies evs)
Nonce NA analz (spies evs))) := by
@@ -143,6 +143,18 @@ theorem no_nonce_NS1_NS2 { h : ns_public evs } :
| inr => rw[spies, knows]; apply analz_mono; apply Set.subset_insert; simp_all
| NS3 => rw[spies, knows]; apply analz_mono; apply Set.subset_insert; simp_all
lemma unique_Nonce_apply_ih {P : Prop}
{h₃ : Nonce NA analz (spies (Says Agent.Spy C X :: evsf))}
{h₁ : M₁ parts (spies evsf)}
{h₂ : M₂ parts (spies evsf)}
{a_ih : M₁ parts (spies evsf)
M₂ parts (spies evsf)
Nonce NA analz (spies evsf) P}
: P := by
simp[spies, knows] at h₃; apply Set.notMem_subset at h₃
· aapply a_ih;
· apply analz_mono; apply Set.subset_insert
lemma unique_NA_apply_ih {P : Prop}
{a_ih : Crypt (pubEK B) Nonce NA, Msg.Agent A parts (spies evsf)
Crypt (pubEK B') Nonce NA, Msg.Agent A' parts (spies evsf)
@@ -151,9 +163,7 @@ lemma unique_NA_apply_ih {P : Prop}
{h₁ : Crypt (pubEK B) Nonce NA, Msg.Agent A parts (spies evsf)}
{h₂ : Crypt (pubEK B') Nonce NA, Msg.Agent A' parts (spies evsf)}
: P := by
simp[spies, knows] at h₃; apply Set.notMem_subset at h₃
· aapply a_ih;
· apply analz_mono; apply Set.subset_insert
aapply unique_Nonce_apply_ih (h₁ := h₁) (h₂ := h₂)
lemma unique_NA_contradict
{h₃ : Nonce NA analz (spies (Says Agent.Spy B X :: evsf))}
@@ -207,31 +217,368 @@ theorem unique_NA { h : ns_public evs } :
| inr => aapply unique_NA_apply_ih
| inr => aapply unique_NA_apply_ih
| NS1 _ _ a_ih => intro h₁ h₂ h₃; simp at h₁; cases h₁ with
| inl => sorry
| inr => simp at h₂; cases h₂ with
| inl h₂ => simp at h₃; rw[analz_Crypt] at h
rcases h₂ with _, nonce_eq, _; rw[nonce_eq] at h₃; simp at h₃;
| inl h₁ => simp at h₂; cases h₂ with
| inl h₂ => rcases h₁ with h₁, _; rcases h₂ with h₂, _;
apply injective_publicKey at h;
apply injective_publicKey at h₂;
simp_all;
| inr h₂ => apply parts.body at h₂; apply parts.fst at h₂;
apply parts_knows_Spy_subset_used at h₂; simp_all;
| inr h₁ => simp at h₂; cases h₂ with
| inl h₂ => apply parts.body at h₁; apply parts.fst at h₁;
apply parts_knows_Spy_subset_used at h₁; simp_all;
| inr => aapply unique_NA_apply_ih;
| NS2 => sorry
| NS3 => sorry
| NS2 _ _ _ a_ih => intro h₁ h₂ h₃; simp_all; apply a_ih
apply Set.notMem_subset at h₃
· apply h₃;
· apply_rules [analz_mono, Set.subset_insert]
| NS3 _ _ _ a_ih => intro h₁ h₂ h₃; simp_all; apply a_ih;
apply Set.notMem_subset at h₃
· apply h₃;
· apply_rules [analz_mono, Set.subset_insert]
-- Spy does not see the nonce sent in NS1 if A and B are secure
theorem Spy_not_see_NA { h : ns_public evs }:
theorem Spy_not_see_NA { h : ns_public evs }
{ not_bad_A : A bad }
{ not_bad_B : B bad } :
Says A B (Crypt (pubEK B) Nonce NA, Agent A) evs
A bad
B bad
Nonce NA analz (spies evs) := by
intro h
induction h <;> simp_all [analz_insertI, no_nonce_NS1_NS2]
intro h₁ h₄
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
apply Fake_analz_insert at a; apply a at h₄; simp_all; cases h₁ with
| inl h => rcases h with l, _; simp_all [Spy_in_bad];
| inr h => cases h₄ with
| inl h₄ => cases h₄; apply a_ih at h; contradiction;
| inr => apply a_ih at h; contradiction;
| NS1 _ a a_ih => simp_all; cases h₁ with
| inl h => rcases h with _, _, _, h, _; simp_all; apply a
apply parts_knows_Spy_subset_used
aapply analz_subset_parts
| inr h => apply analz_insert_Crypt_subset at h₄; cases h₄ with
| inl h₄ => contradiction;
| inr h₄ => simp at h₄; cases h₄
· simp_all; apply a; apply Says_imp_used at h;
apply used_parts_subset_parts at h; simp at h; apply h;
tauto;
· simp_all;
| 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 c := b; have d := a₁; have e := 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
-- 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 }
{ not_bad_B : B bad } :
Says A B (Crypt (pubEK B) Nonce NA, Agent A) evs
Says B' A (Crypt (pubEK B) Nonce NA, Nonce NB, Agent B) evs
Says B A (Crypt (pubEK B) Nonce NA, Nonce NB, Agent B) evs
:= by
intro h₁ h₂;
-- have snsNA := h₁; apply Spy_not_see_NA at snsNA <;> try assumption
apply Says_imp_parts_knows_Spy at h₂
-- use unique_NA to show that B' = B
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
have snsNA := h₁; apply Spy_not_see_NA at snsNA <;> try assumption
cases h₁
· have _ := Spy_in_bad; contradiction
· right; simp at h₂; cases h₂ with
| inl h₂ => apply Fake_parts_sing at a; apply a at h₂; cases h₂ with
| inl h₂ => aapply a_ih; cases h₂ with
| inj => aapply analz_subset_parts
| crypt h => apply False.elim; apply snsNA
apply MPair_synth_analz.mp at h; rcases h with l , _;
aapply analz_spies_mono
| inr h₂ => aapply a_ih;
| inr => aapply a_ih;
· 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;
| 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₂; cases h₂ with
| inl h => apply Says_imp_parts_knows_Spy at a
apply Says_imp_parts_knows_Spy at b
rcases h with e₁ , e₂ , e₃, e₄
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
| inr => right; aapply a_ih
| NS3 _ _ a a_ih => simp at h₁; simp at h₂; right; aapply a_ih
-- 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)
Nonce NA analz (spies evs)
Says A B (Crypt (pubEK B) Nonce NA, Agent A) evs
:= by
intro h₁ h₂
induction h with
| Nil => simp[spies] at h₁; rw[knows] at h₁; simp[initState] at h₁
| Fake _ a a_ih => simp at h₁; cases h₁ with
| inl h₁ => apply Fake_parts_sing at a; apply a at h₁; cases h₁ with
| inl h₁ => cases h₁ with
| inj h₁ => right; apply analz_subset_parts at h₁; aapply a_ih
aapply analz_spies_mono_neg
| crypt h₁ => apply False.elim;
apply MPair_synth_analz.mp at h₁
rcases h₁ with h₁, _; aapply analz_spies_mono_neg
| inr => right; aapply a_ih; aapply analz_spies_mono_neg
| inr h₁ => right; aapply a_ih; aapply analz_spies_mono_neg
| NS1 _ _ a_ih => simp at h₁; cases h₁ with
| inl h₁ => rcases h₁ with e₁, e₂, e₃; apply injective_publicKey at e₁
simp_all
| inr => 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
-- Authenticity Properties obtained from `NS2`
-- Helper lemmas for unique_NB
lemma unique_NB_apply_ih {P : Prop}
{ a_ih :
Crypt (pubEK A) Nonce NA, Nonce NB, Msg.Agent B parts (spies evsf)
Crypt (pubEK A') Nonce NA', Nonce NB, Msg.Agent B' parts (spies evsf)
Nonce NB analz (spies evsf) P }
{ h₁ : Crypt (pubEK A) Nonce NA, Nonce NB, Msg.Agent B parts (spies evsf) }
{ h₂ : Crypt (pubEK A') Nonce NA', Nonce NB, Msg.Agent B' parts (spies evsf) }
{ h₃ : Nonce NB analz (spies (Says Agent.Spy B X :: evsf)) }
: P := by
aapply unique_Nonce_apply_ih (h₁ := h₁) (h₂ := h₂) (h₃ := h₃)
lemma unique_NB_contradict
{ h₃ : Nonce NB analz (spies (Says Agent.Spy B X :: evsf)) }
{ h₂ : synth (analz (spies evsf)) Nonce NA', Nonce NB, Msg.Agent B' }
{P : Prop}
: P := by
apply MPair_synth_analz.mp at h₂; apply False.elim
rcases h₂ with _, r; cases r with
| inj r => aapply analz_spies_mono_neg; aapply analz.fst
| mpair r₁ _ => cases r₁; aapply analz_spies_mono_neg
-- Unicity for `NS2`: nonce `NB` identifies nonce `NA` and agent `A`
theorem unique_NB { h : ns_public evs } :
(Crypt (pubEK A) Nonce NA, Nonce NB, Agent B parts (spies evs)
(Crypt (pubEK A') Nonce NA', Nonce NB, Agent B' parts (spies evs)
(Nonce NB analz (spies evs)
A = A' NA = NA' B = B'))) := by
-- Proof closely follows that of unique_NA
induction h with
| Nil => aesop (add norm spies, norm knows, safe analz_insertI)
| Fake _ a a_ih =>
apply Fake_parts_sing at a; intro h₁ h₂ h₃;
simp[spies, knows] at h₁; cases h₁ with
| inl h₁ => apply a at h₁; cases h₁ with
| inl h₁ => cases h₁ with
| inj h₁ => simp[spies, knows] at h₂; cases h₂ with
| inl h₂ => apply a at h₂; cases h₂ with
| inl h₂ => cases h₂ with
| inj h₂ => apply analz_subset_parts at h₁
apply analz_subset_parts at h₂
aapply unique_NB_apply_ih
| crypt h₂ => aapply unique_NB_contradict
| inr h₂ => apply analz_subset_parts at h₁
aapply unique_NB_apply_ih
| inr h₂ => apply analz_subset_parts at h₁
aapply unique_NB_apply_ih
| crypt h₁ => aapply unique_NB_contradict
| inr h₁ => simp[spies] at h₁; simp[spies, knows] at h₂; cases h₂ with
| inl h₂ => apply a at h₂; cases h₂ with
| inl h₂ => cases h₂ with
| inj h₂ => apply analz_subset_parts at h₂
aapply unique_NB_apply_ih
| crypt => aapply unique_NB_contradict
| inr => aapply unique_NB_apply_ih
| inr => aapply unique_NB_apply_ih
| inr => simp[spies, knows] at h₂; cases h₂ with
| inl h₂ => apply a at h₂; cases h₂ with
| inl h₂ => cases h₂ with
| inj h₂ => apply analz_subset_parts at h₂
aapply unique_NB_apply_ih
| crypt => aapply unique_NB_contradict
| inr => aapply unique_NB_apply_ih
| inr => aapply unique_NB_apply_ih
| NS1 _ _ a_ih => intro h₁ h₂ h₃; simp at h₁; simp at h₂; aapply a_ih
aapply analz_spies_mono_neg
| NS2 _ _ _ a_ih => intro h₁ h₂ h₃; simp at h₁; simp at h₂; cases h₁ with
| inl h₁ => rcases h₁ with e₁, _; apply injective_publicKey at e₁
cases h₂ with
| inl h₂ => rcases h₂ with e₂, _; apply injective_publicKey at e₂
simp_all
| inr h₂ => apply parts.body at h₂; apply parts.snd at h₂
apply parts.fst at h₂; apply parts_knows_Spy_subset_used at h₂;
simp_all;
| inr h₁ => cases h₂ with
| inl h₂ => apply parts.body at h₁; apply parts.snd at h₁
apply parts.fst at h₁; apply parts_knows_Spy_subset_used at h₁;
simp_all
| inr => aapply a_ih; aapply analz_spies_mono_neg
| NS3 _ _ _ a_ih => intro h₁ h₂ h₃; simp_all; apply a_ih;
apply Set.notMem_subset at h₃
· apply h₃;
· apply_rules [analz_mono, Set.subset_insert]
-- `NB` remains secret
theorem Spy_not_see_NB { 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
Nonce NB analz (spies evs)
:= by
intro h₁ h₄
induction h with
| Nil => simp_all
| Fake _ a a_ih =>
apply Fake_analz_insert at a; apply a at h₄; simp_all; cases h₁ with
| inl h => rcases h with l, _; simp_all [Spy_in_bad];
| inr h => cases h₄ with
| inl h₄ => cases h₄; apply a_ih at h; contradiction;
| inr => apply a_ih at h; contradiction;
| NS1 _ a a_ih => simp at h₁; simp[spies, knows] at h₄
apply analz_insert_Crypt_subset at h₄; simp at h₄
cases h₄ with
| inl e => rw[e] at h₁; apply a; apply parts_knows_Spy_subset_used
apply parts.fst; apply parts.snd; apply parts.body
aapply Says_imp_parts_knows_Spy
| inr => aapply a_ih
| NS2 _ not_used_NB a a_ih => simp at h₁; simp[spies, knows] at h₄;
cases h₁ with
| inl h => rcases h with _, _, e₃, _; apply injective_publicKey at e₃;
simp_all; apply not_used_NB; apply parts_knows_Spy_subset_used;
aapply analz_subset_parts
| inr h => apply analz_insert_Crypt_subset at h₄; simp at h₄; cases h₄ with
| inl e => aapply a_ih; rw[e]; apply Says_imp_parts_knows_Spy at a
apply Says_imp_parts_knows_Spy at h; rw[e] at h
aapply no_nonce_NS1_NS2
| inr h => cases h
· simp_all; apply not_used_NB; apply parts_knows_Spy_subset_used
apply parts.fst; apply parts.snd; apply parts.body
aapply Says_imp_parts_knows_Spy
· aapply a_ih
| @NS3 evs3 _ B' _ _ _ _ a₁ a₂ a_ih =>
cases h₁ with | tail _ b =>
simp at h₄; by_cases bad_B' : Key (invKey (pubEK B')) analz (spies evs3)
· have aC := bad_B'; apply analz_subset_parts at bad_B'
apply Spy_see_priEK.mp at bad_B'; have c := b; apply a_ih at c;
apply analz_insert_Decrypt at aC; rw[aC] at h₄; simp at h₄; cases h₄ with
| inl h₄ =>
apply Says_imp_parts_knows_Spy at a₂
apply Says_imp_parts_knows_Spy at b; rw[h₄] at b
apply unique_NB at a₂; apply a₂ at b;
rw[h₄] at c; simp_all; assumption
| inr h₄ => aapply a_ih
· apply analz_Crypt at aC; rw[aC] at h₄; simp at h₄; aapply a_ih;
-- 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 }
{ 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
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 h₂; cases h₁ with
| inl => simp_all[Spy_in_bad]
| inr h₁ => cases h₂ with
| inl h₂ => apply Fake_parts_sing at a; apply a at h₂; cases h₂ with
| inl h₂ => simp at h₂; cases h₂ with
| inj => aapply a_ih; aapply analz_subset_parts;
| crypt h₂ => cases h₂; apply Spy_not_see_NB at h₁ <;> simp_all
| inr => aapply a_ih
| inr => aapply a_ih
| 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
| NS3 _ a₁ a₂ a_ih => simp at h₁; simp at h₂; cases h₂ with
| inl h₂ => simp_all; left; rcases h₂ with e₁, _
apply injective_publicKey at e₁; simp_all
have h₁c := h₁
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 Spy_not_see_NB at h₁c
apply a₂ at h₁c
all_goals simp_all
| inr => right; aapply a_ih
-- 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 }:
A bad
B bad
theorem B_trusts_protocol { h : ns_public evs }
{ not_bad_A : A bad }
{ not_bad_B : B bad } :
Crypt (pubEK B) (Nonce NB) parts (spies evs)
Says B A (Crypt (pubEK A) Nonce NA, Nonce NB, Agent B) evs
Says A B (Crypt (pubEK B) Nonce NA, Agent A) evs := by
intro h
induction h <;> simp_all [analz_insertI, no_nonce_NS1_NS2]
intro h₁ h₂
induction h with
| Nil => simp_all
| Fake _ a a_ih => right; simp at h₁; simp at h₂; cases h₂ with
| inl => simp_all[Spy_in_bad]
| inr h₂ => cases h₁ with
| inl h₁ => apply Fake_parts_sing at a; apply a at h₁; cases h₁ with
| inl h₁ => simp at h₁; cases h₁ with
| inj => aapply a_ih; aapply analz_subset_parts
| crypt h₁ => cases h₁; apply Spy_not_see_NB at h₂ <;> simp_all
| inr => aapply a_ih
| inr => aapply a_ih
| 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
| NS3 _ a₁ a₂ a_ih => simp at h₁; simp at h₂; cases h₁ with
| inl h₁ => simp_all; rcases h₁ with e₁, _
apply injective_publicKey at e₁; simp_all
have h₂c := h₂
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 Spy_not_see_NB at h₂c
apply a₂ at h₂c
all_goals simp_all
| inr => right; aapply a_ih
end NS_Public