Maxima で綴る数学の旅

紙と鉛筆の代わりに、数式処理システムMaxima / Macsyma を使って、数学を楽しみましょう

完全秘匿性のLean4による形式化のまとめ Githubで公開

最近の記事では暗号とその安全性証明の基礎を勉強したいと思い、シャノンの完全秘匿性やそれを実装するワンタイムパッド暗号、完全秘匿性を持つ暗号における鍵の長さに関する定理の証明などを勉強しました。安永さん(東工大の先生ですね)の本を購入し、また公開されているPDFなどを大いに参考にさせていただきました。

 

  • 暗号システムと完全秘匿性の定義
  • ワンタイムパッド暗号の定義と完全秘匿性を満たすことの証明
  • 完全秘匿性を満たす暗号での鍵集合と平文集合の大きさに関する定理の証明

を行い、そのLean4での形式化を紹介してきました。最後の定理については前回の記事でその証明の流れを説明しました。

 

 

上記全てをGithubにレポジトリとして公開しましたので、興味のある人はぜひ見てみてください。レポジトリはこちらです。

 

github.com

 

上記のリポジトリにもありますが、とりあえず前回の証明のフルバージョンを見たい方のために証明を貼っておきます。

 

import PerfectSecrecy.PerfectSecrecy_Def
open PMF
open Set


variable {M K C : Type}
variable [Fintype M] [Inhabited M] [DecidableEq M]
variable [Fintype K] [Inhabited K]
variable [Fintype C] [Inhabited C] [DecidableEq C]

def full_support {T : Type} (A : PMF T) :Prop := ∀t:T, t∈A.support

 

omit [Fintype C] [Inhabited C]
theorem K_GE_M (Enc : K → M → C) (Dec : K → C → M) (Gen : PMF K) :
    (full_support Gen ∧ correctness Enc Dec ∧ perfect_secrecy Enc Gen)
    → Fintype.card K ≥ Fintype.card M := by
  intro FullGen_CR_PS

  by_contra K_M
  push_neg at K_M

  have m₀:M := default
  have k₀:K := default
  let c₀:C := Enc k₀ m₀
  have hc₀ : c₀=Enc k₀ m₀ := by rfl

  let f : K → M := fun k => Dec k c₀
  -- let S₀ := {m:M | ∃k:K, m=Dec k c₀}
  let S₀ := Finset.image f Finset.univ

 

  have S₀_le_K: S₀.card ≤ @Fintype.elems.card K := by
    exact Finset.card_image_le

  have S₀_lt_M : S₀.card < Fintype.card M := by
    exact Nat.lt_of_le_of_lt S₀_le_K K_M

 

  obtain ⟨m₁, hm₁⟩ : ∃m₁:M, ¬ m₁ ∈ S₀ := by
    by_contra hc
    push_neg at hc
    have : S₀=Finset.univ := by
      exact Finset.eq_univ_iff_forall.mpr hc
    simp_rw [this] at S₀_lt_M
    exact (lt_self_iff_false Finset.univ.card).mp S₀_lt_M

 

  have Enc_m1_ne_c₀ : ∀ k : K, Enc k m₁ ≠ c₀ := by
    intro k
    by_contra contra
    apply hm₁
    have correct:= FullGen_CR_PS.2.1 k m₁
    rw [contra] at correct
    rw [Finset.mem_image]
    use k
    constructor
    · exact Finset.mem_univ k
    · exact correct

 

  have Enc_m1_zero : (Enc_dist Enc Gen m₁) c₀ = 0 := by
    simp only [Enc_dist, Bind.bind, PMF.bind_apply, PMF.pure_apply]
    rw [tsum_eq_sum]
    · apply Finset.sum_eq_zero
      intro k _
      have : c₀ ≠ Enc k m₁ := by exact fun a => Enc_m1_ne_c₀ k (id (Eq.symm a))
      rw [if_neg this]
      simp
    · intro k _
      have : c₀ ≠ Enc k m₁ := by exact fun a => Enc_m1_ne_c₀ k (id (Eq.symm a))
      rw [if_neg this]
      simp
    · exact Finset.empty

 

  have Enc_m0_pos : (Enc_dist Enc Gen m₀) c₀ > 0 := by
    simp only [Enc_dist, Bind.bind, PMF.bind_apply, PMF.pure_apply]
    have single_le_tsum: (fun a => Gen a * if c₀ = Enc a m₀ then 1 else 0) k₀
      ≤ (∑' (a : K), Gen a * if c₀ = Enc a m₀ then 1 else 0) := by
      exact ENNReal.le_tsum k₀
    have single_gt_zero: 0<(fun a => Gen a * if c₀ = Enc a m₀ then 1 else 0) k₀ := by
      simp_all [c₀]
      have : k₀∈ Gen.support := by
        apply FullGen_CR_PS.1
      exact (apply_pos_iff Gen k₀).mpr this
    apply lt_of_lt_of_le single_gt_zero
    simp_all

 

  have ps := FullGen_CR_PS.2.2 m₀ m₁ c₀
  simp_all