Skip to content

Commit 199b2bc

Browse files
committed
ワークフローと依存関係の更新、Shannon完全秘密性に関する新しいコードの追加
1 parent 7c7204d commit 199b2bc

11 files changed

Lines changed: 427 additions & 0 deletions
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Create Release
2+
3+
on:
4+
push:
5+
branches:
6+
- 'main'
7+
- 'master'
8+
paths:
9+
- 'lean-toolchain'
10+
11+
jobs:
12+
lean-release-tag:
13+
name: Add Lean release tag
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: write
17+
steps:
18+
- name: lean-release-tag action
19+
uses: leanprover-community/lean-release-tag@v1
20+
with:
21+
do-release: true
22+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Lean Action CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
9+
permissions:
10+
contents: read # Read access to repository contents
11+
pages: write # Write access to GitHub Pages
12+
id-token: write # Write access to ID tokens
13+
14+
jobs:
15+
build:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
- uses: leanprover/lean-action@v1
21+
- uses: leanprover-community/docgen-action@v1

.github/workflows/update.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Update Dependencies
2+
3+
on:
4+
# schedule: # Sets a schedule to trigger the workflow
5+
# - cron: "0 8 * * *" # Every day at 08:00 AM UTC (see https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule)
6+
workflow_dispatch: # Allows the workflow to be triggered manually via the GitHub interface
7+
8+
jobs:
9+
check-for-updates: # Determines which updates to apply.
10+
runs-on: ubuntu-latest
11+
outputs:
12+
is-update-available: ${{ steps.check-for-updates.outputs.is-update-available }}
13+
new-tags: ${{ steps.check-for-updates.outputs.new-tags }}
14+
steps:
15+
- name: Run the action
16+
id: check-for-updates
17+
uses: leanprover-community/mathlib-update-action@v1
18+
# START CONFIGURATION BLOCK 1
19+
# END CONFIGURATION BLOCK 1
20+
do-update: # Runs the upgrade, tests it, and makes a PR/issue/commit.
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: write # Grants permission to push changes to the repository
24+
issues: write # Grants permission to create or update issues
25+
pull-requests: write # Grants permission to create or update pull requests
26+
needs: check-for-updates
27+
if: ${{ needs.check-for-updates.outputs.is-update-available }}
28+
strategy: # Runs for each update discovered by the `check-for-updates` job.
29+
max-parallel: 1 # Ensures that the PRs/issues are created in order.
30+
matrix:
31+
tag: ${{ fromJSON(needs.check-for-updates.outputs.new-tags) }}
32+
steps:
33+
- name: Run the action
34+
id: update-the-repo
35+
uses: leanprover-community/mathlib-update-action/do-update@v1
36+
with:
37+
tag: ${{ matrix.tag }}
38+
# START CONFIGURATION BLOCK 2
39+
on_update_succeeds: pr # Create a pull request if the update succeeds
40+
on_update_fails: issue # Create an issue if the update fails
41+
# END CONFIGURATION BLOCK 2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.lake

Foundation.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import Foundation.Basic

Foundation/Basic.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Foundation.SymmetricEncryption
2+
import Foundation.ShannonPerfectSecrecy
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import Mathlib.Data.Finset.Card
2+
import Mathlib.Data.Fintype.Card
3+
import Mathlib.Data.Fintype.BigOperators
4+
import Mathlib.Data.Rat.Init
5+
import Mathlib.Algebra.Field.Rat
6+
import Mathlib.Algebra.GroupWithZero.Units.Basic
7+
import Mathlib.Algebra.BigOperators.Group.Finset.Basic
8+
import Mathlib.Tactic.FieldSimp
9+
import Foundation.SymmetricEncryption
10+
11+
/-
12+
Shannon perfect secrecy specific code lives in its own namespace so that the
13+
common-key structure is decoupled from distributional properties.
14+
-/
15+
namespace ShannonPerfectSecrecy
16+
17+
open SymmetricEncryption
18+
open scoped BigOperators
19+
20+
variable {Key Msg Ciph : Type _}
21+
22+
section FiniteKeys
23+
24+
variable [Fintype Key] [DecidableEq Ciph]
25+
26+
/-- Number of keys that map a message `m` to a ciphertext `c`. -/
27+
def ciphertextCount (scheme : SymmetricEncryption Key Msg Ciph) (m : Msg) (c : Ciph) : ℕ :=
28+
Fintype.card { k : Key // scheme.enc k m = c }
29+
30+
/-- Probability of obtaining ciphertext `c` when encrypting `m` with a uniform random key. -/
31+
def ciphertextProbability (scheme : SymmetricEncryption Key Msg Ciph) (m : Msg) (c : Ciph) : ℚ :=
32+
(ciphertextCount scheme m c : ℚ) / Fintype.card Key
33+
34+
/-- Shannon perfect secrecy: ciphertext distributions do not depend on the plaintext. -/
35+
def perfectSecrecy (scheme : SymmetricEncryption Key Msg Ciph) : Prop :=
36+
∀ m₁ m₂ c, ciphertextProbability scheme m₁ c = ciphertextProbability scheme m₂ c
37+
38+
/-- Number of keys for which the adversary outputs `true` on the ciphertext of `m`. -/
39+
def adversaryWinCount (scheme : SymmetricEncryption Key Msg Ciph) (adv : Ciph → Bool)
40+
(m : Msg) : ℕ :=
41+
Fintype.card { k : Key // adv (scheme.enc k m) = true }
42+
43+
/-- Probability that an adversary outputs `true` when given the ciphertext of `m`. -/
44+
def adversaryWinProbability (scheme : SymmetricEncryption Key Msg Ciph) (adv : Ciph → Bool)
45+
(m : Msg) : ℚ :=
46+
(adversaryWinCount scheme adv m : ℚ) / Fintype.card Key
47+
48+
/-- Perfect indistinguishability: every adversary sees identical distributions for any messages. -/
49+
def perfectIndistinguishability (scheme : SymmetricEncryption Key Msg Ciph) : Prop :=
50+
∀ adv m₁ m₂,
51+
adversaryWinProbability scheme adv m₁ = adversaryWinProbability scheme adv m₂
52+
53+
section
54+
variable [Nonempty Key]
55+
56+
private def keyCardinalityNeZero : (Fintype.card Key : ℚ) ≠ 0 := by
57+
have hpos : 0 < Fintype.card Key := Fintype.card_pos_iff.mpr inferInstance
58+
have hne : Fintype.card Key ≠ 0 := Nat.pos_iff_ne_zero.mp hpos
59+
exact_mod_cast hne
60+
61+
lemma perfectSecrecy_iff_card (scheme : SymmetricEncryption Key Msg Ciph) :
62+
perfectSecrecy scheme ↔
63+
∀ m₁ m₂ c,
64+
ciphertextCount scheme m₁ c = ciphertextCount scheme m₂ c := by
65+
classical
66+
constructor
67+
· intro h m₁ m₂ c
68+
have h' := h m₁ m₂ c
69+
have hCount : ciphertextCount scheme m₁ c = ciphertextCount scheme m₂ c := by
70+
simpa [ciphertextProbability, keyCardinalityNeZero] using h'
71+
exact hCount
72+
· intro h m₁ m₂ c
73+
have h' : (ciphertextCount scheme m₁ c : ℚ) = ciphertextCount scheme m₂ c := by
74+
exact_mod_cast h m₁ m₂ c
75+
simp [ciphertextProbability, h', div_eq_mul_inv]
76+
77+
omit [DecidableEq Ciph] in
78+
lemma perfectIndistinguishability_iff_card
79+
(scheme : SymmetricEncryption Key Msg Ciph) :
80+
perfectIndistinguishability scheme ↔
81+
∀ adv m₁ m₂,
82+
adversaryWinCount scheme adv m₁ = adversaryWinCount scheme adv m₂ := by
83+
classical
84+
constructor
85+
· intro h adv m₁ m₂
86+
have h' := h adv m₁ m₂
87+
have hCount :
88+
adversaryWinCount scheme adv m₁ = adversaryWinCount scheme adv m₂ := by
89+
simpa [adversaryWinProbability, keyCardinalityNeZero] using h'
90+
exact hCount
91+
· intro h adv m₁ m₂
92+
have h' :
93+
(adversaryWinCount scheme adv m₁ : ℚ) = adversaryWinCount scheme adv m₂ := by
94+
exact_mod_cast h adv m₁ m₂
95+
simp [adversaryWinProbability, h', div_eq_mul_inv]
96+
97+
end
98+
99+
section
100+
variable [Fintype Ciph]
101+
102+
private lemma adversaryWinCount_card_sigma
103+
(scheme : SymmetricEncryption Key Msg Ciph) (adv : Ciph → Bool) (m : Msg) :
104+
adversaryWinCount scheme adv m =
105+
Fintype.card
106+
(Σ c : { c : Ciph // adv c = true },
107+
{ k : Key // scheme.enc k m = c }) := by
108+
classical
109+
refine Fintype.card_congr ?_
110+
refine
111+
{ toFun := ?_, invFun := ?_, left_inv := ?_, right_inv := ?_ }
112+
· intro k
113+
refine ⟨⟨scheme.enc k m, k.property⟩, ⟨k, rfl⟩⟩
114+
· intro k
115+
rcases k with ⟨⟨c, hc⟩, ⟨k, hk⟩⟩
116+
refine ⟨k, ?_⟩
117+
simpa [hk] using hc
118+
· intro k
119+
rcases k with ⟨k, hk⟩
120+
simp
121+
· intro k
122+
rcases k with ⟨⟨c, hc⟩, ⟨k, hk⟩⟩
123+
cases hk
124+
simp
125+
126+
private lemma adversaryWinCount_eq_sum
127+
(scheme : SymmetricEncryption Key Msg Ciph) (adv : Ciph → Bool) (m : Msg) :
128+
adversaryWinCount scheme adv m =
129+
∑ c : { c : Ciph // adv c = true },
130+
ciphertextCount scheme m c.1 := by
131+
classical
132+
have hσ :=
133+
adversaryWinCount_card_sigma (scheme := scheme) (adv := adv) (m := m)
134+
have hCards :
135+
Fintype.card
136+
(Σ c : { c : Ciph // adv c = true },
137+
{ k : Key // scheme.enc k m = c }) =
138+
∑ c : { c : Ciph // adv c = true },
139+
Fintype.card { k : Key // scheme.enc k m = c.1 } :=
140+
(Fintype.card_sigma
141+
(α := fun c : { c : Ciph // adv c = true } =>
142+
{ k : Key // scheme.enc k m = c }))
143+
have hσ' := hσ.trans hCards
144+
have hσ'' :
145+
adversaryWinCount scheme adv m =
146+
∑ c : { c : Ciph // adv c = true },
147+
ciphertextCount scheme m c.1 := by
148+
calc
149+
adversaryWinCount scheme adv m =
150+
∑ c : { c : Ciph // adv c = true },
151+
Fintype.card { k : Key // scheme.enc k m = c.1 } := hσ'
152+
_ = ∑ c : { c : Ciph // adv c = true },
153+
ciphertextCount scheme m c.1 := by
154+
simp [ciphertextCount]
155+
exact hσ''
156+
157+
end
158+
159+
section
160+
variable [Nonempty Key] [Fintype Ciph]
161+
162+
theorem perfectSecrecy_iff_perfectIndistinguishability
163+
(scheme : SymmetricEncryption Key Msg Ciph) :
164+
perfectSecrecy scheme ↔ perfectIndistinguishability scheme := by
165+
classical
166+
constructor
167+
· intro h
168+
have hCount :=
169+
(perfectSecrecy_iff_card (scheme := scheme)).1 h
170+
refine
171+
(perfectIndistinguishability_iff_card (scheme := scheme)).2 ?_
172+
intro adv m₁ m₂
173+
have hTerm :
174+
∀ c : { c : Ciph // adv c = true },
175+
ciphertextCount scheme m₁ c.1 = ciphertextCount scheme m₂ c.1 := by
176+
intro c
177+
simpa using hCount m₁ m₂ c.1
178+
have hSum :
179+
(∑ c : { c : Ciph // adv c = true }, ciphertextCount scheme m₁ c.1) =
180+
∑ c : { c : Ciph // adv c = true }, ciphertextCount scheme m₂ c.1 := by
181+
simpa using congrArg
182+
(fun f :
183+
{ c : Ciph // adv c = true } → ℕ =>
184+
∑ c : { c : Ciph // adv c = true }, f c) (funext hTerm)
185+
simpa [adversaryWinCount_eq_sum (scheme := scheme)] using hSum
186+
· intro h
187+
have hCount :=
188+
(perfectIndistinguishability_iff_card (scheme := scheme)).1 h
189+
refine
190+
(perfectSecrecy_iff_card (scheme := scheme)).2 ?_
191+
intro m₁ m₂ c₀
192+
classical
193+
let adv : Ciph → Bool := fun c => if c = c₀ then true else false
194+
have hAdv :
195+
adversaryWinCount scheme adv m₁ =
196+
adversaryWinCount scheme adv m₂ := hCount adv m₁ m₂
197+
have hWin :
198+
∀ m, adversaryWinCount scheme adv m = ciphertextCount scheme m c₀ := by
199+
intro m
200+
unfold adversaryWinCount ciphertextCount
201+
simp [adv]
202+
have hWin₁ := hWin m₁
203+
have hWin₂ := hWin m₂
204+
simpa [hWin₁, hWin₂] using hAdv
205+
206+
end
207+
208+
end FiniteKeys
209+
210+
end ShannonPerfectSecrecy
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Mathlib.Algebra.Group.Defs
2+
3+
/-- Simple record for deterministic symmetric-key encryption. -/
4+
structure SymmetricEncryption (Key Msg Ciph : Type _) where
5+
enc : Key → Msg → Ciph
6+
dec : Key → Ciph → Msg
7+
correct : ∀ k m, dec k (enc k m) = m
8+
9+
namespace SymmetricEncryption
10+
11+
variable {Key Msg Ciph : Type _}
12+
13+
-- Common-key specific lemmas would live in this namespace.
14+
15+
end SymmetricEncryption

0 commit comments

Comments
 (0)