3. Shamir Scheme
We describe the concrete instantiation of a threshold secret sharing scheme introduced by Shamir in 1979. We will prove at the end of this section that it is an instance of threshold access structure
shamirRealizedScheme
In particular, the Shamir scheme realizes the threshold access structure
\Gamma_{t,n} = \{A \subseteq \mathcal{P} : |A| \ge t\}
over a finite field \mathbb{F} with cardinality |\mathbb{F}| > n.
Construction. Let s \in \mathbb{F} be the secret to be shared
among n participants. The dealer associates each participant
P_i with a distinct non-zero field element x_i \in \mathbb{F} \setminus \{0\}.
Polynomial Encoding.
Fix a threshold t. The dealer chooses t-1 coefficients a_1, \dots, a_{t-1}
uniformly at random from \mathbb{F} and constructs the polynomial
f(x) \in \mathbb{F}[x] of degree at most t-1:
f(x) = s + \sum_{j=1}^{t-1} a_j x^j.
Here, the constant term is the secret, i.e., f(0) = s.
The share for participant P_i is the evaluation of the polynomial
at their assigned point:
y_i = f(x_i).
The dealer distributes the share (x_i, y_i) to participant P_i.
Reconstruction via Interpolation.
Reconstruction is guaranteed by the property that a polynomial of degree t-1
is uniquely determined by its values at t distinct points. For any
authorized set of participants B with |B| \ge t, the secret s = f(0)
can be recovered using Lagrange interpolation.
Let L_j(x) be the Lagrange basis polynomials associated with the set B:
L_j(x) = \prod_{\substack{k \in B \\ k \neq j}} \frac{x - x_k}{x_j - x_k}.
The polynomial f(x) can be expressed as
f(x) = \sum_{j \in B} y_j L_j(x).
To recover the secret, the participants simply evaluate the interpolation formula at x=0:
s = f(0) = \sum_{j \in B} y_j \Big( \prod_{\substack{k \in B \\ k \neq j}} \frac{0 - x_k}{x_j - x_k} \Big).
-- Import the library of Lagrange interpolation -- from Linear Algebra import Mathlib.LinearAlgebra.Lagrange -- import AccessStructure and SecretSharing Scheme import SecretSharingScheme.Section_1_Access_Structure import SecretSharingScheme.Section_2_Secret_Sharing_Scheme
We put the Lean program for Shamir scheme inside a
noncomputable section.
noncomputable section ShamirScheme
In addition to the definitions from AccessStructure and SecretSharingScheme,
we also need the APIs from BigOperators, Finset, Matrix, Polynomial.
namespace ShamirScheme
open AccessStructure
open SecretSharingScheme
open BigOperators Finset Matrix Polynomial
open scoped Classical
universe u
The variable F denotes a field.
variable {F : Type*} [Field F]
The polynomial used in Shamir secret scheme is called shamir_poly t F.
It is a polynomial in polynomial t over a finite field F.
/-- Shamir's secret sharing polynomial evaluation.
s is the secret (constant term).
m contains the t-1 random coefficients
m_1, ..., m_{t-1}.
z is the evaluation point. -/
def shamir_poly (t : ℕ) (s : F)
(m : Fin (t - 1) → F) (z : F) : F :=
s + ∑ j : Fin (t - 1), m j * z ^ (j.val + 1)
/--
When `F` is finite, define the uniform cistribution of
the coefficients.
-/
noncomputable def uniform_coeffs [Fintype F] (t : ℕ) :
PMF (Fin (t - 1) → F) :=
PMF.uniformOfFintype (Fin (t - 1) → F)
A helper lemma showing that the size of a finite field is at least 2.
/--
The cardinality of a finite field is at least 2.
-/
theorem FiniteField.card_ge_two (F : Type*)
[Field F] [Fintype F]
: Fintype.card F ≥ 2 := F:Type u_2inst✝¹:Field Finst✝:Fintype F⊢ Fintype.card F ≥ 2
F:Type u_2inst✝¹:Field Finst✝:Fintype Fh:0 ≠ 1⊢ Fintype.card F ≥ 2
F:Type u_2inst✝¹:Field Finst✝:Fintype Fh:0 ≠ 1h_card:Fintype.card F > 1⊢ Fintype.card F ≥ 2
All goals completed! 🐙
Define the Shamir secret sharing shceme.
/-- Shamir's Secret Sharing Scheme. -/
def shamirScheme [Fintype F] (n t : ℕ)
(x : Fin n → F)
(_h_distinct : Function.Injective x)
(_h_nonzero : ∀ i, x i ≠ 0)
: SecretSharingScheme n where
Secret := F
Random := Fin (t - 1) → F
hSecret := inferInstance
hSecret_card := FiniteField.card_ge_two F
Share := fun _ => F
hShare := fun _ => inferInstance
hRandom := inferInstance
hRandomNonempty := inferInstance
μ := uniform_coeffs t
dealer := fun s m i => shamir_poly t s m (x i)
theorem threshold_auth_iff (n t : ℕ) (B : Set (Fin n)) :
B ∈ (thresholdAccessStructure n t).auth
↔ t ≤ B.ncard := n:ℕt:ℕB:Set (Fin n)⊢ B ∈ (thresholdAccessStructure n t).auth ↔ t ≤ B.ncard
-- By definition of the threshold access structure,
-- `B` is authorized if and only if there exists a subset
-- `A` with exactly `t` elements such that `A`
-- is a subset of `B`.
n:ℕt:ℕB:Set (Fin n)⊢ (∃ a, a.ncard = t ∧ a ⊆ B) ↔ t ≤ B.ncard
-- If there exists a subset `a` of `B` with
-- cardinality `t`, then clearly `t \leq B.ncard`.
n:ℕt:ℕB:Set (Fin n)⊢ (∃ a, a.ncard = t ∧ a ⊆ B) → t ≤ B.ncardn:ℕt:ℕB:Set (Fin n)⊢ t ≤ B.ncard → ∃ a, a.ncard = t ∧ a ⊆ B;
n:ℕt:ℕB:Set (Fin n)⊢ (∃ a, a.ncard = t ∧ a ⊆ B) → t ≤ B.ncard n:ℕt:ℕB:Set (Fin n)a:Set (Fin n)ha₁:a.ncard = tha₂:a ⊆ B⊢ t ≤ B.ncard
All goals completed! 🐙
n:ℕt:ℕB:Set (Fin n)⊢ t ≤ B.ncard → ∃ a, a.ncard = t ∧ a ⊆ B -- If `B` has at least t elements, then we can choose a
-- subset a of `B` with exactly `t` elements.
n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncard⊢ ∃ a, a.ncard = t ∧ a ⊆ B
obtain ⟨a, ha⟩ :
∃ a : Finset (Fin n), a.card = t ∧
∀ x ∈ a, x ∈ B := n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncard⊢ ∃ a, #a = t ∧ ∀ x ∈ a, x ∈ B
n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncardthis:∃ t_1 ⊆ B, t_1.ncard = t⊢ ∃ a, #a = t ∧ ∀ x ∈ a, x ∈ B;
n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncarda:Set (Fin n)ha₁:a ⊆ Bha₂:a.ncard = t⊢ ∃ a, #a = t ∧ ∀ x ∈ a, x ∈ B;
exact ⟨ a.toFinset,
n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncarda:Set (Fin n)ha₁:a ⊆ Bha₂:a.ncard = t⊢ #a.toFinset = t All goals completed! 🐙,
fun x hx => ha₁ <| n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncarda:Set (Fin n)ha₁:a ⊆ Bha₂:a.ncard = tx:Fin nhx:x ∈ a.toFinset⊢ x ∈ a All goals completed! 🐙 ⟩ ;
exact ⟨ a, n:ℕt:ℕB:Set (Fin n)ht:t ≤ B.ncarda:Finset (Fin n)ha:#a = t ∧ ∀ x ∈ a, x ∈ B⊢ (↑a).ncard = t All goals completed! 🐙, fun x hx => ha.2 x hx ⟩
Reconstruction in Shamir scheme.
noncomputable def shamir_reconstruction
(n t : ℕ)
(x : Fin n → F)
(B : Set (Fin n))
(hB : B ∈ (thresholdAccessStructure n t).auth)
(shares : (i : B) → F) : F :=
let h_card : t ≤ B.ncard
:= (threshold_auth_iff n t B).mp hB
let S := Classical.choose
(Set.exists_subset_card_eq h_card)
let S_finset := S.toFinset
let shares_ext : Fin n → F := fun i =>
if h : i ∈ B then shares ⟨i, h⟩ else 0
((Lagrange.interpolate S_finset x) shares_ext).eval 0
Shamir polynomial as a linear map on the i-th coefficient.
The function shamir_linear_map n t x B maps
an index i to an element in the field F.
def shamir_linear_map
(n t : ℕ)
(x : Fin n → F)
(B : Set (Fin n))
(r : Fin (t - 1) → F) : B → F :=
fun i => ∑ j : Fin (t - 1), r j * (x i) ^ (j.val + 1)
The Shamir linear map is a surjective function.
lemma shamir_linear_map_surjective (n t : ℕ)
(x : Fin n → F)
(h_distinct : Function.Injective x)
(h_nonzero : ∀ i, x i ≠ 0)
(B : Set (Fin n))
(hB : B.ncard < t) :
Function.Surjective (shamir_linear_map n t x B) := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < t⊢ Function.Surjective (shamir_linear_map n t x B)
-- Since `B` has fewer than `t` elements,
-- the system of equations given by the evaluations
-- is underdetermined, and thus there exists a `p`
-- such that `p(i) = s_i` for each `i` in `B`.
have h_underdetermined :
∀ (s : B → F), ∃ p : Fin (t - 1) → F, ∀ i : B, ∑ j
: Fin (t - 1), p j * x i ^ (j.val + 1) = s i
:= F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < t⊢ Function.Surjective (shamir_linear_map n t x B)
-- Since the Vandermonde matrix is invertible,
-- the system of equations has a unique solution
-- for any right-hand side.
have h_vandermonde_inv :
∀ (s : B → F), ∃ p : Fin (B.ncard) → F,
∀ i : B, ∑ j : Fin (B.ncard),
p j * x i ^ (j.val + 1) = s i := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < t⊢ Function.Surjective (shamir_linear_map n t x B)
-- Since the x_i are distinct, the Vandermonde matrix
-- is invertible, so the system has a unique solution.
have h_vandermonde_inv :
∀ (s : B → F), ∃ p : Fin (B.ncard) → F,
∀ i : B, ∑ j : Fin (B.ncard), p j * x i ^ (j.val)
= s i := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < t⊢ Function.Surjective (shamir_linear_map n t x B)
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → F⊢ ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s i;
-- Since `B` is a finite set, we can choose a
-- bijection function `f : Fin B.ncard ≃ B`.
obtain ⟨f, hf⟩ : ∃ f : Fin B.ncard ≃ B, True := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → F⊢ ∃ f, True
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), ¬x i = 0B:Set (Fin n)hB:B.ncard < ts:↑B → F⊢ Nonempty (Fin B.ncard ≃ ↑B);
exact ⟨ Fintype.equivOfCardEq <|
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), ¬x i = 0B:Set (Fin n)hB:B.ncard < ts:↑B → F⊢ Fintype.card (Fin B.ncard) = Fintype.card ↑B All goals completed! 🐙 ⟩;
obtain ⟨p, hp⟩ :
∃ p : Fin B.ncard → F, ∀ i : Fin B.ncard,
∑ j : Fin B.ncard, p j * x (f i) ^ (j.val)
= s (f i) := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:True⊢ ∃ p, ∀ (i : Fin B.ncard), ∑ j, p j * x ↑(f i) ^ ↑j = s (f i)
have h_vandermonde_inv :
Matrix.det (Matrix.of (fun i j : Fin B.ncard =>
x (f i) ^ (j.val))) ≠ 0 := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:True⊢ ∃ p, ∀ (i : Fin B.ncard), ∑ j, p j * x ↑(f i) ^ ↑j = s (f i)
erw [ Matrix.det_vandermonde F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:True⊢ ∏ i, ∏ j ∈ Ioi i, (x ↑(f j) - x ↑(f i)) ≠ 0;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:True⊢ ∀ (x x_1 : Fin B.ncard), x < x_1 → ¬↑(f x_1) = ↑(f x);
All goals completed! 🐙;
have h_vandermonde_inv :
∀ (b : Fin B.ncard → F), ∃ p : Fin B.ncard → F,
Matrix.mulVec (Matrix.of
(fun i j : Fin B.ncard =>
x (f i) ^ (j.val))) p = b := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:True⊢ ∃ p, ∀ (i : Fin B.ncard), ∑ j, p j * x ↑(f i) ^ ↑j = s (f i)
exact fun b =>
⟨ Matrix.mulVec ( Matrix.of (
fun i j : Fin B.ncard =>
x ( f i ) ^ ( j.val ) ) )⁻¹ b,
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:Trueh_vandermonde_inv:(of fun i j => x ↑(f i) ^ ↑j).det ≠ 0b:Fin B.ncard → F⊢ (of fun i j => x ↑(f i) ^ ↑j) *ᵥ (of fun i j => x ↑(f i) ^ ↑j)⁻¹ *ᵥ b = b All goals completed! 🐙 ⟩;
exact Exists.elim ( h_vandermonde_inv fun i =>
s ( f i ) ) fun p hp => ⟨ p, fun i =>
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:Trueh_vandermonde_inv✝:(of fun i j => x ↑(f i) ^ ↑j).det ≠ 0h_vandermonde_inv:∀ (b : Fin B.ncard → F), ∃ p, (of fun i j => x ↑(f i) ^ ↑j) *ᵥ p = bp:Fin B.ncard → Fhp:(of fun i j => x ↑(f i) ^ ↑j) *ᵥ p = fun i => s (f i)i:Fin B.ncard⊢ ∑ j, p j * x ↑(f i) ^ ↑j = s (f i) All goals completed! 🐙 ⟩;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:Truep:Fin B.ncard → Fhp:∀ (i : Fin B.ncard), ∑ j, p j * x ↑(f i) ^ ↑j = s (f i)⊢ ∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s i
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:Truep:Fin B.ncard → Fhp:∀ (i : Fin B.ncard), ∑ j, p j * x ↑(f i) ^ ↑j = s (f i)i:↑B⊢ ∑ j, p j * x ↑i ^ ↑j = s i
simpa using hp ( f.symm i )
|> fun h => F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:↑B → Ff:Fin B.ncard ≃ ↑Bhf:Truep:Fin B.ncard → Fhp:∀ (i : Fin B.ncard), ∑ j, p j * x ↑(f i) ^ ↑j = s (f i)i:↑Bh:∑ j, p j * x ↑(f (f.symm i)) ^ ↑j = s (f (f.symm i))⊢ ∑ j, p j * x ↑i ^ ↑j = s i All goals completed! 🐙
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s is:↑B → F⊢ ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s i / x ↑i⊢ ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ ↑j = s i / x ↑i⊢ ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i;
All goals completed! 🐙;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → F⊢ ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i⊢ ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i⊢ ∀ (i : ↑B), ∑ j, (fun j => if hj : ↑j < B.ncard then p ⟨↑j, hj⟩ else 0) j * x ↑i ^ (↑j + 1) = s i
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ ∑ j, (fun j => if hj : ↑j < B.ncard then p ⟨↑j, hj⟩ else 0) j * x ↑i ^ (↑j + 1) = s i;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ ∑ j, (fun j => if hj : ↑j < B.ncard then p ⟨↑j, hj⟩ else 0) j * x ↑i ^ (↑j + 1) = ∑ j, p j * x ↑i ^ (↑j + 1) ;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ ∑ x_1 ∈ image (fun j => ⟨↑j, ⋯⟩) univ, (fun j => if hj : ↑j < B.ncard then p ⟨↑j, hj⟩ else 0) x_1 * x ↑i ^ (↑x_1 + 1) =
∑ j, p j * x ↑i ^ (↑j + 1)F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ ∀ x_1 ∈ univ,
x_1 ∉ image (fun j => ⟨↑j, ⋯⟩) univ →
(fun j => if hj : ↑j < B.ncard then p ⟨↑j, hj⟩ else 0) x_1 * x ↑i ^ (↑x_1 + 1) = 0
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ ∑ x_1 ∈ image (fun j => ⟨↑j, ⋯⟩) univ, (fun j => if hj : ↑j < B.ncard then p ⟨↑j, hj⟩ else 0) x_1 * x ↑i ^ (↑x_1 + 1) =
∑ j, p j * x ↑i ^ (↑j + 1) All goals completed! 🐙
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_vandermonde_inv:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin B.ncard → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ ∀ (x_1 : Fin (t - 1)), (∀ (x : Fin B.ncard), ¬↑x = ↑x_1) → ∀ (h : ↑x_1 < B.ncard), p ⟨↑x_1, ⋯⟩ = 0 ∨ x ↑i = 0;
All goals completed! 🐙;
-- At this point, we have proved h_undedetermined
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_underdetermined:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i⊢ ∀ (b : ↑B → F), ∃ a, shamir_linear_map n t x B a = b
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_underdetermined:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → F⊢ ∃ a, shamir_linear_map n t x B a = s
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_underdetermined:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin (t - 1) → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s i⊢ ∃ a, shamir_linear_map n t x B a = s
exact ⟨ p,
funext fun i => F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < th_underdetermined:∀ (s : ↑B → F), ∃ p, ∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s is:↑B → Fp:Fin (t - 1) → Fhp:∀ (i : ↑B), ∑ j, p j * x ↑i ^ (↑j + 1) = s ii:↑B⊢ shamir_linear_map n t x B p i = s i All goals completed! 🐙 ⟩
Assume that for all y in B, the size of the fiber {x // f x = y}
is a constant k. if a is drawn uniformly from A, then
the image f a is uniformly distributed.
lemma map_uniform_of_fiber_card_eq {A B : Type u}
[Fintype A] [Fintype B] [Nonempty A] [Nonempty B]
(f : A → B) (k : ℕ)
(h_fibers : ∀ y : B, Fintype.card {x // f x = y} = k) :
PMF.map f (PMF.uniformOfFintype A)
= PMF.uniformOfFintype B := A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = k⊢ PMF.map f (PMF.uniformOfFintype A) = PMF.uniformOfFintype B
-- By definition of PMF.map, we have:
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ (PMF.map f (PMF.uniformOfFintype A)) y = (PMF.uniformOfFintype B) y
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ (∑ a, if y = f a then (↑(Fintype.card A))⁻¹ else 0) = (↑(Fintype.card B))⁻¹;
-- Since there are `k` elements in `A` that map to `y`,
-- the sum of the probabilities of these elements is
-- $k \cdot \frac{1}{|A|} = \frac{k}{|A|}$.
have h_sum :
∑' a : A, (if y = f a then (1 : ENNReal)
/ (Fintype.card A) else 0) = (k : ENNReal)
/ (Fintype.card A) := A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = k⊢ PMF.map f (PMF.uniformOfFintype A) = PMF.uniformOfFintype B
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ (∑ b ∈ ?m.56, if y = f b then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ ∀ b ∉ ?m.56, (if y = f b then 1 / ↑(Fintype.card A) else 0) = 0A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ Finset A;
any_goals All goals completed! 🐙;
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ (∑ b ∈ ?m.56, if y = f b then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A) A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ (∑ x with f x = y, if y = f x then (↑(Fintype.card A))⁻¹ else 0) = ↑(#{x | f x = y}) / ↑(Fintype.card A);
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ ∑ x with f x = y, (↑(Fintype.card A))⁻¹ = ↑(#{x | f x = y}) / ↑(Fintype.card A)
All goals completed! 🐙
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:B⊢ ∀ b ∉ ?m.56, (if y = f b then 1 / ↑(Fintype.card A) else 0) = 0 All goals completed! 🐙;
-- Since there are `k` elements in `A` that map to each
-- `y`, the total number of elements in `A` is
-- `k \cdot |B|`.
have h_card_A : Fintype.card A = k * Fintype.card B := A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = k⊢ PMF.map f (PMF.uniformOfFintype A) = PMF.uniformOfFintype B
have h_card_A : Fintype.card A
= ∑ y : B, Fintype.card { x : A // f x = y } := A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = k⊢ PMF.map f (PMF.uniformOfFintype A) = PMF.uniformOfFintype B
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)⊢ Fintype.card A = ∑ x, #{x_1 | f x_1 = x};
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)⊢ Fintype.card A = ∑ x, ∑ i, if f i = x then 1 else 0;
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)⊢ Fintype.card A = ∑ y, ∑ x, if f y = x then 1 else 0 ; All goals completed! 🐙 ;
All goals completed! 🐙;
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)h_card_A:Fintype.card A = k * Fintype.card Bhk:k = 0⊢ (∑ a, if y = f a then (↑(Fintype.card A))⁻¹ else 0) = (↑(Fintype.card B))⁻¹A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ (∑ a, if y = f a then (↑(Fintype.card A))⁻¹ else 0) = (↑(Fintype.card B))⁻¹ A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)h_card_A:Fintype.card A = k * Fintype.card Bhk:k = 0⊢ (∑ a, if y = f a then (↑(Fintype.card A))⁻¹ else 0) = (↑(Fintype.card B))⁻¹A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑' (a : A), if y = f a then 1 / ↑(Fintype.card A) else 0) = ↑k / ↑(Fintype.card A)h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ (∑ a, if y = f a then (↑(Fintype.card A))⁻¹ else 0) = (↑(Fintype.card B))⁻¹ A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ ↑k * (↑k * ↑(Fintype.card B))⁻¹ = (↑(Fintype.card B))⁻¹;
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ (↑k * (↑k * ↑(Fintype.card B))⁻¹).toReal = (↑(Fintype.card B))⁻¹.toRealA:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ ↑k * (↑k * ↑(Fintype.card B))⁻¹ ≠ ⊤A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ (↑(Fintype.card B))⁻¹ ≠ ⊤ A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ (↑k * (↑k * ↑(Fintype.card B))⁻¹).toReal = (↑(Fintype.card B))⁻¹.toRealA:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ ↑k * (↑k * ↑(Fintype.card B))⁻¹ ≠ ⊤A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ (↑(Fintype.card B))⁻¹ ≠ ⊤
All goals completed! 🐙;
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ ↑k * ((↑(Fintype.card B))⁻¹ * (↑k)⁻¹) = (↑(Fintype.card B))⁻¹ All goals completed! 🐙;
A:Type uB:Type uinst✝³:Fintype Ainst✝²:Fintype Binst✝¹:Nonempty Ainst✝:Nonempty Bf:A → Bk:ℕh_fibers:∀ (y : B), Fintype.card { x // f x = y } = ky:Bh_sum:(∑ a, if y = f a then (↑k * ↑(Fintype.card B))⁻¹ else 0) = ↑k * (↑k * ↑(Fintype.card B))⁻¹h_card_A:Fintype.card A = k * Fintype.card Bhk:¬k = 0⊢ ¬↑k * (↑k * ↑(Fintype.card B))⁻¹ = ⊤ All goals completed! 🐙
lemma shamir_fiber_card_constant [Fintype F]
(n t : ℕ) (x : Fin n → F)
(h_distinct : Function.Injective x)
(h_nonzero : ∀ i, x i ≠ 0)
(B : Set (Fin n))
(hB : B.ncard < t) (s : F) :
∃ k, ∀ y : B → F, Fintype.card { m : Fin (t - 1) → F //
(fun i : B => shamir_poly t s m (x i)) = y } = k := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:F⊢ ∃ k, ∀ (y : ↑B → F), Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = y } = k
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:F⊢ ∀ (y : ↑B → F),
Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = y } =
Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) };
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fy:↑B → F⊢ Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = y } =
Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }
have h_fibers :
∀ y : B → F, ∃ m₀ : Fin (t - 1) → F,
(fun i : B => shamir_poly t s m₀ (x i)) = y := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:F⊢ ∃ k, ∀ (y : ↑B → F), Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = y } = k
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fy✝:↑B → Fy:↑B → F⊢ ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = y
obtain ⟨m₀, hm₀⟩
: ∃ m₀ : Fin (t - 1) → F, (fun i : B =>
∑ j : Fin (t - 1), m₀ j * (x i) ^ (j.val + 1))
= fun i : B => y i - s := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fy✝:↑B → Fy:↑B → F⊢ ∃ m₀, (fun i => ∑ j, m₀ j * x ↑i ^ (↑j + 1)) = fun i => y i - s
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fy✝:↑B → Fy:↑B → Fthis:Function.Surjective (shamir_linear_map n t x B)⊢ ∃ m₀, (fun i => ∑ j, m₀ j * x ↑i ^ (↑j + 1)) = fun i => y i - s;
All goals completed! 🐙;
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fy✝:↑B → Fy:↑B → Fm₀:Fin (t - 1) → Fhm₀:(fun i => ∑ j, m₀ j * x ↑i ^ (↑j + 1)) = fun i => y i - s⊢ (fun i => shamir_poly t s m₀ (x ↑i)) = y; All goals completed! 🐙
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → F⊢ Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) } =
Fintype.card { m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) };
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → F⊢ { m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) } ≃
{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) };
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }⊢ (fun i => shamir_poly t s (↑m - m₀) (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i)F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }⊢ (fun i => shamir_poly t s (↑m + m₀) (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i)F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }⊢ (fun m => ⟨↑m + m₀, ⋯⟩) ((fun m => ⟨↑m - m₀, ⋯⟩) m) = mF:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }⊢ (fun m => ⟨↑m - m₀, ⋯⟩) ((fun m => ⟨↑m + m₀, ⋯⟩) m) = m F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }⊢ (fun i => shamir_poly t s (↑m - m₀) (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i)F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }⊢ (fun i => shamir_poly t s (↑m + m₀) (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i)F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }⊢ (fun m => ⟨↑m + m₀, ⋯⟩) ((fun m => ⟨↑m - m₀, ⋯⟩) m) = mF:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:Fh_fibers:∀ (y : ↑B → F), ∃ m₀, (fun i => shamir_poly t s m₀ (x ↑i)) = ym₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }⊢ (fun m => ⟨↑m - m₀, ⋯⟩) ((fun m => ⟨↑m + m₀, ⋯⟩) m) = m All goals completed! 🐙;
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < th_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), shamir_poly t s m₀ (x a) = y ⟨a, b⟩⊢ ∀ a ∈ B, shamir_poly t s (↑m - m₀) (x a) = shamir_poly t s 0 (x a) intro i F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < th_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), shamir_poly t s m₀ (x a) = y ⟨a, b⟩i:Fin nhi:i ∈ B⊢ shamir_poly t s (↑m - m₀) (x i) = shamir_poly t s 0 (x i);
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s m₀ (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < th_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), shamir_poly t s m₀ (x a) = y ⟨a, b⟩i:Fin nhi:i ∈ Bthis:shamir_poly t s (↑m) (x ↑⟨i, hi⟩) = shamir_poly t s m₀ (x ↑⟨i, hi⟩)⊢ shamir_poly t s (↑m - m₀) (x i) = shamir_poly t s 0 (x i) ;
All goals completed! 🐙
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < th_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), shamir_poly t s m₀ (x a) = y ⟨a, b⟩⊢ ∀ a ∈ B, shamir_poly t s (↑m + m₀) (x a) = shamir_poly t s m₀ (x a) intro i F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < th_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), shamir_poly t s m₀ (x a) = y ⟨a, b⟩i:Fin nhi:i ∈ B⊢ shamir_poly t s (↑m + m₀) (x i) = shamir_poly t s m₀ (x i);
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < th_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), shamir_poly t s m₀ (x a) = y ⟨a, b⟩i:Fin nhi:i ∈ Bthis:shamir_poly t s (↑m) (x ↑⟨i, hi⟩) = shamir_poly t s 0 (x ↑⟨i, hi⟩)⊢ shamir_poly t s (↑m + m₀) (x i) = shamir_poly t s m₀ (x i) ;
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xB:Set (Fin n)s:Fm₀:Fin (t - 1) → Fm:{ m // (fun i => shamir_poly t s m (x ↑i)) = fun i => shamir_poly t s 0 (x ↑i) }h_nonzero:∀ (i : Fin n), ¬x i = 0hB:B.ncard < ti:Fin nhi:i ∈ Bh_fibers:∀ (y : ↑B → F), ∃ m₀, ∀ (a : Fin n) (b : a ∈ B), s + ∑ j, m₀ j * x a ^ (↑j + 1) = y ⟨a, b⟩this:∑ x_1, ↑m x_1 * x i ^ (↑x_1 + 1) = 0⊢ ∑ x_1, (↑m x_1 + m₀ x_1) * x i ^ (↑x_1 + 1) = ∑ j, m₀ j * x i ^ (↑j + 1)
All goals completed! 🐙
Prove that each share in the Shamir scheme is uniform distributed.
lemma [Fintype F] (n t : ℕ)
(x : Fin n → F)
(h_distinct : Function.Injective x)
(h_nonzero : ∀ i, x i ≠ 0)
(B : Set (Fin n)) (hB : B.ncard < t) (s : F) :
PMF.map (fun r => fun (i : B) =>
shamir_poly t s r (x i)) (uniform_coeffs t)
= PMF.uniformOfFintype (B → F) := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:F⊢ PMF.map (fun r i => shamir_poly t s r (x ↑i)) (uniform_coeffs t) = PMF.uniformOfFintype (↑B → F)
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:F⊢ ∀ (y : ↑B → F), Fintype.card { x_1 // (fun i => shamir_poly t s x_1 (x ↑i)) = y } = ?kF:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B.ncard < ts:F⊢ ℕ;
All goals completed! 🐙
Prove that Shamir scheme has perfect secrecy.
theorem shamir_perfect_security [Fintype F] (n t : ℕ)
(x : Fin n → F)
(h_distinct : Function.Injective x)
(h_nonzero : ∀ i, x i ≠ 0) :
PerfectSecurity (shamirScheme n t x h_distinct h_nonzero)
(thresholdAccessStructure n t) := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0⊢ (shamirScheme n t x h_distinct h_nonzero).PerfectSecurity (thresholdAccessStructure n t)
intro B F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auth⊢ ∀ (s s' : (shamirScheme n t x h_distinct h_nonzero).Secret),
PMF.map (fun r => (shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B)
(shamirScheme n t x h_distinct h_nonzero).μ =
PMF.map (fun r => (shamirScheme n t x h_distinct h_nonzero).shares_of_set s' r B)
(shamirScheme n t x h_distinct h_nonzero).μ F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secret⊢ ∀ (s' : (shamirScheme n t x h_distinct h_nonzero).Secret),
PMF.map (fun r => (shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B)
(shamirScheme n t x h_distinct h_nonzero).μ =
PMF.map (fun r => (shamirScheme n t x h_distinct h_nonzero).shares_of_set s' r B)
(shamirScheme n t x h_distinct h_nonzero).μ F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ PMF.map (fun r => (shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B)
(shamirScheme n t x h_distinct h_nonzero).μ =
PMF.map (fun r => (shamirScheme n t x h_distinct h_nonzero).shares_of_set s' r B)
(shamirScheme n t x h_distinct h_nonzero).μ;
have h_uniform :
∀ s : F, PMF.map (fun r : Fin (t - 1) → F
=> fun (i : B) => shamir_poly t s r (x i))
(uniform_coeffs t)
= PMF.uniformOfFintype (B → F) := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0⊢ (shamirScheme n t x h_distinct h_nonzero).PerfectSecurity (thresholdAccessStructure n t)
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ Function.Injective xF:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ ∀ (i : Fin n), x i ≠ 0F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ B.ncard < t;
--· exact (FiniteField.card_ge_two F);
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ Function.Injective x All goals completed! 🐙;
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ ∀ (i : Fin n), x i ≠ 0 All goals completed! 🐙;
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0B:Set (Fin n)hB:B ∉ (thresholdAccessStructure n t).auths:(shamirScheme n t x h_distinct h_nonzero).Secrets':(shamirScheme n t x h_distinct h_nonzero).Secret⊢ B.ncard < t All goals completed! 🐙;
All goals completed! 🐙
An alternate description of Shamir polynomial using Polynomial type
def shamir_polynomial
(t : ℕ) (s : F) (m : Fin (t - 1) → F) : Polynomial F :=
Polynomial.C s + ∑ i : Fin (t - 1),
Polynomial.C (m i) * Polynomial.X ^ (i.val + 1)
/-- shamir_poly and shamir_polynomial have the same
mathematical meaning-/
lemma shamir_polynomial_eval (t : ℕ) (s : F)
(m : Fin (t - 1) → F) (z : F) :
(shamir_polynomial t s m).eval z
= shamir_poly t s m z := F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → Fz:F⊢ eval z (shamir_polynomial t s m) = shamir_poly t s m z
-- By definition of polynomial evaluation,
-- we can expand the left-hand side.
F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → Fz:F⊢ s + ∑ x, m x * z ^ (↑x + 1) = shamir_poly t s m z;
-- By definition of polynomial evaluation,
-- we can expand the left-hand side to
-- match the right-hand side.
All goals completed! 🐙
lemma shamir_polynomial_degree_le
(t : ℕ) (s : F) (m : Fin (t - 1) → F) :
(shamir_polynomial t s m).natDegree ≤ t - 1 := F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → F⊢ (shamir_polynomial t s m).natDegree ≤ t - 1
-- The polynomial is constructed by adding a constant
-- term `s` and a sum of terms `m_i * x^(i+1)`.
-- Each term in the sum is a monomial of degree `i+1`,
-- where `i` ranges from 0 to `t-2`. The highest degree
-- term here is when `i` is `t-2`, which gives `x^(t-1)`.
-- So the degree of the polynomial should be `t-1`.
have h_deg :
(shamir_polynomial t s m).natDegree
≤ Finset.sup (Finset.univ :
Finset (Fin (t - 1))) (fun i => i.val + 1) := F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → F⊢ (shamir_polynomial t s m).natDegree ≤ t - 1
-- The degree of the sum of polynomials is
-- the maximum of their degrees.
have h_deg_sum :
(Finset.sum Finset.univ fun i =>
Polynomial.C (m i) * Polynomial.X
^ ((i : ℕ)+1)).natDegree
≤ Finset.sup (Finset.univ : Finset (Fin (t - 1)))
(fun i => (i : ℕ) + 1) := F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → F⊢ (shamir_polynomial t s m).natDegree ≤ t - 1
F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → F⊢ ∀ b ∈ univ, (natDegree ∘ fun i => C (m i) * X ^ (↑i + 1)) b ≤ univ.sup fun i => ↑i + 1;
All goals completed! 🐙;
exact le_trans
( Polynomial.natDegree_add_le _ _ )
( max_le ( F:Type u_1inst✝:Field Ft:ℕs:Fm:Fin (t - 1) → Fh_deg_sum:(∑ i, C (m i) * X ^ (↑i + 1)).natDegree ≤ univ.sup fun i => ↑i + 1⊢ (C s).natDegree ≤ univ.sup fun i => ↑i + 1 All goals completed! 🐙 ) h_deg_sum );
All goals completed! 🐙
Proof that interpolation formula can reconstruct the secret correctly
/-- Prove that the interpoloation formula for
reconstruction is correct-/
lemma shamir_interpolation_correct (n t : ℕ)
(x : Fin n → F)
(h_distinct : Function.Injective x)
(_h_nonzero : ∀ i, x i ≠ 0)
(s : F) (m : Fin (t - 1) → F)
(B : Set (Fin n))
(hB : B ∈ (thresholdAccessStructure n t).auth)
(ht : t ≠ 0) :
let h_card : t ≤ B.ncard
:= (threshold_auth_iff n t B).mp hB
let S :=
Classical.choose (Set.exists_subset_card_eq h_card)
let S_finset := S.toFinset
let shares :
(i : B) → F := fun i => shamir_poly t s m (x i)
let shares_ext :
Fin n → F := fun i => if h : i ∈ B then
shares ⟨i, h⟩ else 0
(Lagrange.interpolate S_finset x) shares_ext
= shamir_polynomial t s m := F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ let h_card := ⋯;
let S := Classical.choose ⋯;
let S_finset := S.toFinset;
let shares := fun i => shamir_poly t s m (x ↑i);
let shares_ext := fun i => if h : i ∈ B then shares ⟨i, h⟩ else 0;
(Lagrange.interpolate S_finset x) shares_ext = shamir_polynomial t s m
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ Finset FF:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ (((Lagrange.interpolate (Classical.choose ⋯).toFinset x) fun i =>
if h : i ∈ B then (fun i => shamir_poly t s m (x ↑i)) ⟨i, h⟩ else 0) -
shamir_polynomial t s m).degree <
↑(#?refine'_1)F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ∀ x_1 ∈ ?refine'_1,
eval x_1
((Lagrange.interpolate (Classical.choose ⋯).toFinset x) fun i =>
if h : i ∈ B then (fun i => shamir_poly t s m (x ↑i)) ⟨i, h⟩ else 0) =
eval x_1 (shamir_polynomial t s m)
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ Finset F All goals completed! 🐙;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ (((Lagrange.interpolate (Classical.choose ⋯).toFinset x) fun i =>
if h : i ∈ B then (fun i => shamir_poly t s m (x ↑i)) ⟨i, h⟩ else 0) -
shamir_polynomial t s m).degree <
↑(#?refine'_1) F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ((Lagrange.interpolate (Classical.choose ⋯).toFinset x) fun i =>
if h : i ∈ B then (fun i => shamir_poly t s m (x ↑i)) ⟨i, h⟩ else 0).degree <
↑(#(image x (Classical.choose ⋯).toFinset))F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ (shamir_polynomial t s m).degree < ↑(#(image x (Classical.choose ⋯).toFinset));
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ((Lagrange.interpolate (Classical.choose ⋯).toFinset x) fun i =>
if h : i ∈ B then (fun i => shamir_poly t s m (x ↑i)) ⟨i, h⟩ else 0).degree <
↑(#(image x (Classical.choose ⋯).toFinset)) F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ #(image x (Classical.choose ⋯).toFinset) = #(Classical.choose ⋯).toFinsetF:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ Set.InjOn x ↑(Classical.choose ⋯).toFinset;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ #(image x (Classical.choose ⋯).toFinset) = #(Classical.choose ⋯).toFinset All goals completed! 🐙;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ Set.InjOn x ↑(Classical.choose ⋯).toFinset All goals completed! 🐙;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ (shamir_polynomial t s m).degree < ↑(#(image x (Classical.choose ⋯).toFinset)) F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ↑(shamir_polynomial t s m).natDegree < ↑(#(image x (Classical.choose ⋯).toFinset))
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ↑(shamir_polynomial t s m).natDegree < ↑(#(Classical.choose ⋯).toFinset);
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0this:Classical.choose ⋯ ⊆ B ∧ (Classical.choose ⋯).ncard = t⊢ ↑(shamir_polynomial t s m).natDegree < ↑(#(Classical.choose ⋯).toFinset);
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xs:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).auth_h_nonzero:∀ (i : Fin n), ¬x i = 0ht:¬t = 0this:Classical.choose ⋯ ⊆ B ∧ Fintype.card ↑(Classical.choose ⋯) = t⊢ (shamir_polynomial t s m).natDegree < t;
All goals completed! 🐙
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ∀ x_1 ∈ ?refine'_1,
eval x_1
((Lagrange.interpolate (Classical.choose ⋯).toFinset x) fun i =>
if h : i ∈ B then (fun i => shamir_poly t s m (x ↑i)) ⟨i, h⟩ else 0) =
eval x_1 (shamir_polynomial t s m) F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0⊢ ∀ a ∈ Classical.choose ⋯,
eval (x a)
(∑ i ∈ (Classical.choose ⋯).toFinset,
C (if i ∈ B then shamir_poly t s m (x i) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x i) =
eval (x a) (shamir_polynomial t s m)
intro i F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ eval (x i)
(∑ i ∈ (Classical.choose ⋯).toFinset,
C (if i ∈ B then shamir_poly t s m (x i) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x i) =
eval (x i) (shamir_polynomial t s m);
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ eval (x i) (C (if i ∈ B then shamir_poly t s m (x i) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x i) =
eval (x i) (shamir_polynomial t s m)F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ ∀ b ∈ (Classical.choose ⋯).toFinset,
b ≠ i →
eval (x i) (C (if b ∈ B then shamir_poly t s m (x b) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x b) = 0F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ i ∉ (Classical.choose ⋯).toFinset →
eval (x i) (C (if i ∈ B then shamir_poly t s m (x i) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x i) = 0
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ eval (x i) (C (if i ∈ B then shamir_poly t s m (x i) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x i) =
eval (x i) (shamir_polynomial t s m)F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ ∀ b ∈ (Classical.choose ⋯).toFinset,
b ≠ i →
eval (x i) (C (if b ∈ B then shamir_poly t s m (x b) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x b) = 0F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ i ∉ (Classical.choose ⋯).toFinset →
eval (x i) (C (if i ∈ B then shamir_poly t s m (x i) else 0) * Lagrange.basis (Classical.choose ⋯).toFinset x i) = 0 F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ i ∉ Classical.choose ⋯ →
i ∈ B →
shamir_poly t s m (x i) = 0 ∨
eval (x i) (∏ j ∈ (Classical.choose ⋯).toFinset.erase i, Lagrange.basisDivisor (x i) (x j)) = 0
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ (if i ∈ B then
shamir_poly t s m (x i) *
eval (x i) (∏ j ∈ (Classical.choose ⋯).toFinset.erase i, Lagrange.basisDivisor (x i) (x j))
else 0) =
eval (x i) (shamir_polynomial t s m) F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ shamir_poly t s m (x i) * eval (x i) (∏ j ∈ (Classical.choose ⋯).toFinset.erase i, Lagrange.basisDivisor (x i) (x j)) =
eval (x i) (shamir_polynomial t s m)
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ shamir_poly t s m (x i) * ∏ x_1 ∈ (Classical.choose ⋯).toFinset.erase i, (x i - x x_1)⁻¹ * (x i - x x_1) =
eval (x i) (shamir_polynomial t s m)
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ shamir_poly t s m (x i) * 1 = eval (x i) (shamir_polynomial t s m)
All goals completed! 🐙;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ ∀ b ∈ Classical.choose ⋯,
¬b = i →
b ∈ B →
shamir_poly t s m (x b) = 0 ∨
eval (x i) (∏ j ∈ (Classical.choose ⋯).toFinset.erase b, Lagrange.basisDivisor (x b) (x j)) = 0 intro j F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯j:Fin nhj:j ∈ Classical.choose ⋯⊢ ¬j = i →
j ∈ B →
shamir_poly t s m (x j) = 0 ∨
eval (x i) (∏ j_1 ∈ (Classical.choose ⋯).toFinset.erase j, Lagrange.basisDivisor (x j) (x j_1)) = 0 F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯j:Fin nhj:j ∈ Classical.choose ⋯hij:¬j = i⊢ j ∈ B →
shamir_poly t s m (x j) = 0 ∨
eval (x i) (∏ j_1 ∈ (Classical.choose ⋯).toFinset.erase j, Lagrange.basisDivisor (x j) (x j_1)) = 0 F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯j:Fin nhj:j ∈ Classical.choose ⋯hij:¬j = ihjB:j ∈ B⊢ shamir_poly t s m (x j) = 0 ∨
eval (x i) (∏ j_1 ∈ (Classical.choose ⋯).toFinset.erase j, Lagrange.basisDivisor (x j) (x j_1)) = 0;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯j:Fin nhj:j ∈ Classical.choose ⋯hij:¬j = ihjB:j ∈ B⊢ shamir_poly t s m (x j) = 0 ∨
∏ j_1 ∈ (Classical.choose ⋯).toFinset.erase j, eval (x i) (Lagrange.basisDivisor (x j) (x j_1)) = 0 ;
exact Or.inr ( Finset.prod_eq_zero
(Finset.mem_erase_of_ne_of_mem (Ne.symm hij)
(F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯j:Fin nhj:j ∈ Classical.choose ⋯hij:¬j = ihjB:j ∈ B⊢ i ∈ (Classical.choose ⋯).toFinset All goals completed! 🐙))
( F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯j:Fin nhj:j ∈ Classical.choose ⋯hij:¬j = ihjB:j ∈ B⊢ eval (x i) (Lagrange.basisDivisor (x j) (x i)) = 0 All goals completed! 🐙 ) ) ;
F:Type u_1inst✝:Field Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective x_h_nonzero:∀ (i : Fin n), x i ≠ 0s:Fm:Fin (t - 1) → FB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authht:t ≠ 0i:Fin nhi:i ∈ Classical.choose ⋯⊢ i ∉ Classical.choose ⋯ →
i ∈ B →
shamir_poly t s m (x i) = 0 ∨
eval (x i) (∏ j ∈ (Classical.choose ⋯).toFinset.erase i, Lagrange.basisDivisor (x i) (x j)) = 0 All goals completed! 🐙
/-- Proof of correctness of Shamir secret sharing scheme-/
theorem shamir_scheme_correctness [Fintype F] (n t : ℕ)
(x : Fin n → F)
(h_distinct : Function.Injective x)
(h_nonzero : ∀ i, x i ≠ 0) (ht : t ≠ 0) :
Correctness (shamirScheme n t x h_distinct h_nonzero)
(thresholdAccessStructure n t)
(shamir_reconstruction n t x) := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0⊢ (shamirScheme n t x h_distinct h_nonzero).Correctness (thresholdAccessStructure n t) (shamir_reconstruction n t x)
-- By definition of Shamir's scheme, the polynomial
-- is constructed such that evaluating it at 0
-- gives the secret.
have h_poly_eval :
∀ (s : F) (m : Fin (t - 1) → F),
(shamir_polynomial t s m).eval 0 = s := F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0⊢ (shamirScheme n t x h_distinct h_nonzero).Correctness (thresholdAccessStructure n t) (shamir_reconstruction n t x)
-- By definition of Shamir's polynomial, evaluating
-- it at 0 gives the secret.
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0s:Fm:Fin (t - 1) → F⊢ eval 0 (shamir_polynomial t s m) = s
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0s:Fm:Fin (t - 1) → F⊢ eval 0 (∑ i, C (m i) * X ^ (↑i + 1)) = 0;
All goals completed! 🐙;
intro s F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0h_poly_eval:∀ (s : F) (m : Fin (t - 1) → F), eval 0 (shamir_polynomial t s m) = ss:(shamirScheme n t x h_distinct h_nonzero).Secretr:(shamirScheme n t x h_distinct h_nonzero).Random⊢ ∀ (B : Set (Fin n)) (hB : B ∈ (thresholdAccessStructure n t).auth),
shamir_reconstruction n t x B hB ((shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B) = s F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0h_poly_eval:∀ (s : F) (m : Fin (t - 1) → F), eval 0 (shamir_polynomial t s m) = ss:(shamirScheme n t x h_distinct h_nonzero).Secretr:(shamirScheme n t x h_distinct h_nonzero).RandomB:Set (Fin n)⊢ ∀ (hB : B ∈ (thresholdAccessStructure n t).auth),
shamir_reconstruction n t x B hB ((shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B) = s F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0h_poly_eval:∀ (s : F) (m : Fin (t - 1) → F), eval 0 (shamir_polynomial t s m) = ss:(shamirScheme n t x h_distinct h_nonzero).Secretr:(shamirScheme n t x h_distinct h_nonzero).RandomB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).auth⊢ shamir_reconstruction n t x B hB ((shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B) = s;
F:Type u_1inst✝¹:Field Finst✝:Fintype Fn:ℕt:ℕx:Fin n → Fh_distinct:Function.Injective xh_nonzero:∀ (i : Fin n), x i ≠ 0ht:t ≠ 0h_poly_eval:∀ (s : F) (m : Fin (t - 1) → F), eval 0 (shamir_polynomial t s m) = ss:(shamirScheme n t x h_distinct h_nonzero).Secretr:(shamirScheme n t x h_distinct h_nonzero).RandomB:Set (Fin n)hB:B ∈ (thresholdAccessStructure n t).authe_1✝:(shamirScheme n t x h_distinct h_nonzero).Secret = F⊢ shamir_reconstruction n t x B hB ((shamirScheme n t x h_distinct h_nonzero).shares_of_set s r B) =
eval 0 (shamir_polynomial t s r);
All goals completed! 🐙
Show that Shamir secret sharing scheme is a realization of threshold access structure.
def shamirRealizedScheme [Fintype F] (n t : ℕ)
(x : Fin n → F)
(h_distinct : Function.Injective x)
(h_nonzero : ∀ i, x i ≠ 0)
(ht : t > 0)
: RealizedSecretSharingScheme n
(thresholdAccessStructure n t) := {
shamirScheme n t x h_distinct h_nonzero with
recon := shamir_reconstruction n t x
h_correctness := shamir_scheme_correctness n t x
h_distinct h_nonzero (ne_of_gt ht)
h_security := shamir_perfect_security n t x
h_distinct h_nonzero
}
end ShamirScheme -- namespace
end ShamirScheme --section