-
Notifications
You must be signed in to change notification settings - Fork 110
feat(Cryptography): formalise perfect secrecy and the one-time pad #464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /- | ||
| Copyright (c) 2026 Samuel Schlesinger. All rights reserved. | ||
| Released under Apache 2.0 license as described in the file LICENSE. | ||
| Authors: Samuel Schlesinger | ||
| -/ | ||
|
|
||
| module | ||
|
|
||
| public import Cslib.Crypto.PerfectSecrecy.Defs | ||
| public import Cslib.Crypto.PerfectSecrecy.Internal.PerfectSecrecy | ||
|
|
||
| @[expose] public section | ||
|
|
||
| /-! | ||
| # Perfect Secrecy | ||
|
|
||
| Characterisation theorems for perfect secrecy following | ||
| [KatzLindell2020], Chapter 2. | ||
|
|
||
| ## Main results | ||
|
|
||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.perfectlySecret_iff_ciphertextIndist`: | ||
| ciphertext indistinguishability characterization ([KatzLindell2020], Lemma 2.5) | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.perfectlySecret_iff_posteriorEq`: | ||
| perfect secrecy as equality of posterior and prior distributions | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.perfectlySecret_keySpace_ge`: | ||
| Shannon's theorem, `|K| ≥ |M|` ([KatzLindell2020], Theorem 2.12) | ||
|
|
||
| ## References | ||
|
|
||
| * [J. Katz, Y. Lindell, *Introduction to Modern Cryptography*][KatzLindell2020] | ||
| -/ | ||
|
|
||
| namespace Cslib.Crypto.PerfectSecrecy.EncScheme | ||
|
|
||
| universe u | ||
| variable {M K C : Type u} | ||
|
|
||
| /-- A scheme is perfectly secret iff the ciphertext distribution is | ||
| independent of the plaintext ([KatzLindell2020], Lemma 2.5). -/ | ||
| theorem perfectlySecret_iff_ciphertextIndist (scheme : EncScheme M K C) : | ||
| scheme.PerfectlySecret ↔ scheme.CiphertextIndist := | ||
| ⟨PerfectSecrecy.ciphertextIndist_of_perfectlySecret scheme, | ||
| PerfectSecrecy.perfectlySecret_of_ciphertextIndist scheme⟩ | ||
|
|
||
| /-- Perfect secrecy requires `|K| ≥ |M|` | ||
| ([KatzLindell2020], Theorem 2.12). -/ | ||
| theorem perfectlySecret_keySpace_ge [Finite K] | ||
| (scheme : EncScheme M K C) (h : scheme.PerfectlySecret) : | ||
| Nat.card K ≥ Nat.card M := | ||
| PerfectSecrecy.shannonKeySpace scheme h | ||
|
|
||
| end Cslib.Crypto.PerfectSecrecy.EncScheme |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /- | ||
| Copyright (c) 2026 Samuel Schlesinger. All rights reserved. | ||
| Released under Apache 2.0 license as described in the file LICENSE. | ||
| Authors: Samuel Schlesinger | ||
| -/ | ||
|
|
||
| module | ||
|
|
||
| public import Cslib.Crypto.PerfectSecrecy.Encryption | ||
| public import Mathlib.Probability.ProbabilityMassFunction.Constructions | ||
|
|
||
| @[expose] public section | ||
|
|
||
| /-! | ||
| # Perfect Secrecy: Definitions | ||
|
|
||
| Core definitions for perfect secrecy following [KatzLindell2020], Chapter 2. | ||
|
|
||
| ## Main definitions | ||
|
|
||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.ciphertextDist`: | ||
| ciphertext distribution for a given message | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.jointDist`: | ||
| joint (message, ciphertext) distribution given a message prior | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.marginalCiphertextDist`: | ||
| marginal ciphertext distribution given a message prior | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.posteriorMsgProb`: | ||
| posterior probability `Pr[M = m | C = c]` | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.posteriorMsgDist`: | ||
| posterior message distribution as a `PMF` (defined in the internal file) | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.PerfectlySecret`: | ||
| perfect secrecy ([KatzLindell2020], Definition 2.3) | ||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme.CiphertextIndist`: | ||
| ciphertext indistinguishability ([KatzLindell2020], Lemma 2.5) | ||
| -/ | ||
|
|
||
| namespace Cslib.Crypto.PerfectSecrecy.EncScheme | ||
|
|
||
| universe u | ||
| variable {M K C : Type u} | ||
|
|
||
| /-- The distribution of `Enc_K(m)` when `K ← Gen`. -/ | ||
| noncomputable def ciphertextDist (scheme : EncScheme M K C) (m : M) : PMF C := do | ||
| let k ← scheme.gen | ||
| scheme.enc k m | ||
|
|
||
| /-- Joint distribution of `(M, C)` given a message prior. -/ | ||
| noncomputable def jointDist (scheme : EncScheme M K C) (msgDist : PMF M) : PMF (M × C) := do | ||
| let m ← msgDist | ||
| let c ← scheme.ciphertextDist m | ||
| pure (m, c) | ||
|
|
||
| /-- Marginal ciphertext distribution given a message prior. -/ | ||
| noncomputable def marginalCiphertextDist (scheme : EncScheme M K C) | ||
| (msgDist : PMF M) : PMF C := do | ||
| let m ← msgDist | ||
| scheme.ciphertextDist m | ||
|
|
||
| /-- Posterior probability `Pr[M = m | C = c]`. -/ | ||
| noncomputable def posteriorMsgProb (scheme : EncScheme M K C) | ||
| (msgDist : PMF M) (c : C) (m : M) : ENNReal := | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think scheme.posteriorMsgProb msgDist c is a distribution. It would be good to define it in these terms. It will require a little proof (but do we not already have this in Mathlib? Maybe not). |
||
| scheme.jointDist msgDist (m, c) / scheme.marginalCiphertextDist msgDist c | ||
|
|
||
| /-- An encryption scheme is perfectly secret if `Pr[M = m | C = c] = Pr[M = m]` | ||
| for every prior, message, and ciphertext with positive probability | ||
| ([KatzLindell2020], Definition 2.3). -/ | ||
| def PerfectlySecret (scheme : EncScheme M K C) : Prop := | ||
| ∀ (msgDist : PMF M) (m : M) (c : C), | ||
| c ∈ (scheme.marginalCiphertextDist msgDist).support → | ||
| scheme.posteriorMsgProb msgDist c m = msgDist m | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very nearly equivalent to: The issue is that the types don't match. But I think scheme.posteriorMsgProb msgDist c is a distribution! |
||
|
|
||
| /-- Ciphertext indistinguishability: the ciphertext distribution is the same | ||
| for all messages ([KatzLindell2020], Lemma 2.5). -/ | ||
| def CiphertextIndist (scheme : EncScheme M K C) : Prop := | ||
| ∀ m₀ m₁ : M, scheme.ciphertextDist m₀ = scheme.ciphertextDist m₁ | ||
|
|
||
| end Cslib.Crypto.PerfectSecrecy.EncScheme | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /- | ||
| Copyright (c) 2026 Samuel Schlesinger. All rights reserved. | ||
| Released under Apache 2.0 license as described in the file LICENSE. | ||
| Authors: Samuel Schlesinger | ||
| -/ | ||
|
|
||
| module | ||
|
|
||
| public import Cslib.Init | ||
| public import Mathlib.Probability.ProbabilityMassFunction.Monad | ||
|
|
||
| @[expose] public section | ||
|
|
||
| /-! | ||
| # Private-Key Encryption Schemes (Information-Theoretic) | ||
|
|
||
| An information-theoretic private-key encryption scheme following | ||
| [KatzLindell2020], Definition 2.1. Key generation and encryption are | ||
| probability distributions over arbitrary types, with no computational | ||
| constraints. | ||
|
|
||
| ## Main definitions | ||
|
|
||
| - `Cslib.Crypto.PerfectSecrecy.EncScheme`: | ||
| a private-key encryption scheme (Gen, Enc, Dec) with correctness | ||
|
|
||
| ## References | ||
|
|
||
| * [J. Katz, Y. Lindell, *Introduction to Modern Cryptography*][KatzLindell2020] | ||
| -/ | ||
|
|
||
| namespace Cslib.Crypto.PerfectSecrecy | ||
|
|
||
| /-- | ||
| A private-key encryption scheme over message space `M`, key space `K`, | ||
| and ciphertext space `C` ([KatzLindell2020], Definition 2.1). | ||
| -/ | ||
| structure EncScheme.{u} (M K C : Type u) where | ||
| /-- Probabilistic key generation. -/ | ||
| gen : PMF K | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have briefly spoken about this, but it is worth considering whether rational probabilities might be desirable. The concern would be that sometimes you do want to be able to take limits of probabilities etc.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think given that this is really not going to be reused very much (the rest of the book defined encryption schemes totally differently), I feel we shouldn't define a custom notion of rational distributions just for this. That said, I am very open to computable probability distributions being defined somewhere if they're going to be useful broadly. |
||
| /-- (Possibly randomized) encryption. -/ | ||
| enc : K → M → PMF C | ||
| /-- Deterministic decryption. -/ | ||
| dec : K → C → M | ||
| /-- Decryption inverts encryption for all keys in the support of `gen`. -/ | ||
| correct : ∀ k, k ∈ gen.support → ∀ m c, c ∈ (enc k m).support → dec k c = m | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like the right statement of correctness to me. I wonder if "gen.support" (the set of valid keys) and (enc k m),support (the set of valid encryptions for a give k) want names/definitions (or at least abbreviations).
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me, support feels like the right phrasing, but I am open to suggestions. |
||
|
|
||
| end Cslib.Crypto.PerfectSecrecy | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /- | ||
| Copyright (c) 2026 Samuel Schlesinger. All rights reserved. | ||
| Released under Apache 2.0 license as described in the file LICENSE. | ||
| Authors: Samuel Schlesinger | ||
| -/ | ||
|
|
||
| module | ||
|
|
||
| public import Cslib.Init | ||
| public import Mathlib.Probability.Distributions.Uniform | ||
|
|
||
| @[expose] public section | ||
|
|
||
| /-! | ||
| # One-Time Pad: Internal proofs | ||
|
|
||
| The OTP ciphertext distribution is uniform regardless of message. | ||
| -/ | ||
|
|
||
| namespace Cslib.Crypto.PerfectSecrecy.OTP | ||
|
|
||
| @[reducible] noncomputable def bitVecFintype (n : ℕ) : Fintype (BitVec n) := | ||
| Fintype.ofEquiv (Fin (2 ^ n)) | ||
| ⟨BitVec.ofFin, BitVec.toFin, fun x => by simp, fun x => by simp⟩ | ||
|
|
||
| /-- XOR by a fixed mask is self-inverse on `BitVec`: `c = k ^^^ m ↔ k = c ^^^ m`. -/ | ||
| lemma xor_right_eq_iff {l : ℕ} (c m k : BitVec l) : | ||
| (c = k ^^^ m) ↔ (k = c ^^^ m) := by | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there's a special tactic to discharge bitvec goals. Ask around (I am not sure). This should definitely be upstream.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh neat. I can grep around in Mathlib for it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bv_decide doesn't seem to work, if that's what you meant |
||
| constructor | ||
| · rintro rfl | ||
| rw [BitVec.xor_assoc, BitVec.xor_self, BitVec.xor_zero] | ||
| · rintro rfl | ||
| rw [BitVec.xor_assoc, BitVec.xor_self, BitVec.xor_zero] | ||
|
|
||
| /-- The ciphertext distribution of the OTP is uniform, regardless of the message. -/ | ||
| theorem otp_ciphertextDist_eq_uniform (l : ℕ) (m : BitVec l) : | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| haveI := bitVecFintype l | ||
| (PMF.uniformOfFintype (BitVec l)).bind | ||
| (fun k => PMF.pure (k ^^^ m)) = | ||
| PMF.uniformOfFintype (BitVec l) := by | ||
| haveI := bitVecFintype l | ||
| ext c | ||
| simp only [PMF.bind_apply, PMF.uniformOfFintype_apply, PMF.pure_apply] | ||
| simp_rw [xor_right_eq_iff c m] | ||
| simp | ||
|
|
||
| end Cslib.Crypto.PerfectSecrecy.OTP | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double directory name?