Secret Sharing and Secure Distributed Matrix Multiplication

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 FFintype.card F 2 F:Type u_2inst✝¹:Field Finst✝:Fintype Fh:0 1Fintype.card F 2 F:Type u_2inst✝¹:Field Finst✝:Fintype Fh:0 1h_card:Fintype.card F > 1Fintype.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 Bt 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.toFinsetx 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 < tFunction.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 < tFunction.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 < tFunction.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 < tFunction.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 FNonempty (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 FFintype.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:Bshamir_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 } = kPMF.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 } = kPMF.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:BFinset 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 } = kPMF.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 } = kPMF.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 = 0k * (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 = 0k * (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 = 0k * (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 = 0k * ((↑(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 FFintype.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) FFintype.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, bi:Fin nhi:i Bshamir_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, bi: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, bi:Fin nhi:i Bshamir_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, bi: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, bthis: 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 shamir_shares_uniform [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:FPMF.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).SecretPMF.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).SecretFunction.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).SecretB.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).SecretFunction.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).SecretB.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:Feval 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:Fs + 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 0let 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 0Finset 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 0Finset 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 0Set.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 0Set.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 = ij 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 Bshamir_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 Bshamir_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 Bi (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 Beval (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) Feval 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) Feval 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).authshamir_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 = Fshamir_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