Shamir秘密共享
Shamir秘密共享
作者:hxd
日期:2025年3月28日
1. 秘密共享
秘密 $s$ (通过某种方案)被分为 $n$ 个部分,每个部分称为份额(share),由一个参与者持有,使得
- 由 $k$ 个或多于 $k$ 个参与者所持有的部分信息可重构 $s$
- 由少于 $k$ 个参与者所持有的部分信息则无法重构 $s$
称该方案为 $(k,n)$ 门限秘密共享方案,$k$ 称为门限值。
2. Shamir秘密共享(Shamir Secret Sharing SSS)
Shamir秘密共享(Shamir’s Secret Sharing, SSS) 是一种密码学协议,由 Adi Shamir 在 1979 年提出。它的核心思想是将一个秘密(如密钥或敏感数据)分成多个部分(称为“份额”或“shares”),并将这些份额分发给多个参与者。只有达到一定数量的份额(称为“阈(yu)值”)才能恢复出原始秘密,而少于阈值的份额无法提供任何关于秘密的信息。
SSS 是一种门限秘密共享方案,广泛应用于分布式系统、密码学、数据备份和安全多方计算等领域。
前言
多项式上的 $k$ 个点能够唯一确定小于或等于 $k−1$ 次的多项式一般地,设${(x_1,y_1),…,(x_k,y_k)}$是平面上$k$个不同的点构成的点集,那么在平面上存在唯一的$k-1$次多项式$f(x)=a_0+a_1x+\cdots +a_{k-1}x^{k-1}$通过这$k$个点,其中$a_0,a_1,…a_k-1$是随机数。
确定好门限值$k$和总值$n$,若把秘密 $s$取做$f(0)$ ,为每个参与者生成一个份额$(x_i, y_i)$,其中$y_i = f(x_i)$。$x_i(i=1\cdots n)$作为参与方id,$n$个份额取做$(x_i,f(x_i))(i=1,…n)$,那么利用其中任意$k$个份额可以重构$f(x)$,从而可以得到秘密$s$。
构造
设$GF(q)$为大素数$q$生成的有限域,其中$q\ge n+1$.
秘密$s$是$GF(q)/{0}$上均匀选区的随机数,即$s\in GF(q)/{0}$.
在$GF(q)$上构造一个$k-1$次多项式$f(x)=a_0+a_1x+\cdots +a_{k-1}x^{k-1}$,其中:$a_0=s,a_i\in GF(q)/{0}(i\ne 0)$
$n$个参与者$P_1,P_2…,P_n$,其中$P_i$的份额为$f(i)$。任意$k$个参与者想要得到秘密$s$,可使用
例如:假定一个秘密值$s=45$,要求将其分给10个参与方,至少 3 方参与计算才能够恢复出原始秘密,即 $n=10,k=3$。构造对应的多项式 $f(x)=45+19x+13x^2$。在此多项式上选取连续的整数点作为各个子秘密:
秘密重建
对于 $y_i$ 值的任意 $k$ 个子集,我们可以通过插值找到 $f(x)$ 的多项式系数,然后计算 $s=f(0)$。另一方面,仅知道子集中的 $k−1$ 个并不足以计算出 $s$。
在生成秘密份额的时候,已经确定需要$k$ 个秘密份额来恢复原始秘密。即根据$(x_1,y_1),(x_2,y_2),…,(x_k,y_k)$ 等一系列点构造出原始的多项式 $f(x)$,进而求解得到秘密值 $s=f(0)=a_0$。
由Lagrange插值公式得:给定$n+1$个数据点$(x_0, y_0), (x_1, y_1), \ldots, (x_n, y_n)$,其中所有的$x_i$互不相同,拉格朗日插值多项式$f(x)$可以表示为:
其中,$\ell_i(x)$是拉格朗日基多项式(也称为插值基函数),定义为:
基多项式的性质
每个基多项式$\ell_i(x)$满足:
因此,$P(x_i) = y_i$对所有$i$成立,确保多项式通过所有给定点。
当$j = i$时(即$x=x_{i}$) 基多项式$\ell_i(x)$的定义为:$\ell_i(x) = \prod_{\substack{0 \leq j \leq n \ j \neq i}} \frac{x-x_{j}}{x_{i}-x_{j}}$。将$x=x_{i}$代入:
- 分子部分:$x_i - x_j$(与分母相同)。
- 分母部分:$x_i - x_j$(与分子相同)。
因此,每一项的值为$\frac{x_i - x_j}{x_i - x_j} = 1$,连乘后得到:
$\ell_i(x_i)=\prod_{j\neq i}1=1.$
2.当$j \neq i$时(即$x = x_k$且$k \neq i$)
观察$\ell_i(x)$的连乘积形式:
$\ell_i(x)=\frac{(x-x_0)}{(x_i-x_0)}\cdot\frac{(x-x_1)}{(x_i-x_1)}\cdots\frac{(x-x_{i-1})}{(x_i-x_{i-1})}\cdot\frac{(x-x_{i+1})}{(x_i-x_{i+1})}\cdots\frac{(x-x_n)}{(x_i-x_n)}$
当$x = x_k$($k \neq i$)时,连乘积中必定存在一项分子为$x_k - x_k = 0$(即第$k$项)。因此:
$\ell_i(x_k) = \text{(其他项)} \cdot \frac{x_k - x_k}{x_i - x_k} \cdot \text{(其他项)} = 0.$
直观理解
- $\ell_i(x)$是一个“开关函数”:它在$x_i$处取值为 1,在其他数据点$x_j$($j \neq i$)处强制为 0。
- 插值多项式的构造:通过将每个$y_i$与对应的$\ell_i(x)$相乘后相加($P(x) = \sum y_i \ell_i(x)$),可以确保:
- 在$x = x_i$时,只有$\ell_i(x_i) = 1$,其他基函数均为 0,因此$P(x_i) = y_i$。
- 在其他点$x_j$($j \neq i$),$\ell_i(x_j) = 0$的机制避免了不同$y_j$之间的干扰。
例子验证
假设有 3 个点$(x_0, x_1, x_2)$,基函数$\ell_1(x)$为:
- 在$x = x_1$时:
- 在$x = x_0$或$x = x_2$时:
为了重建秘密,任意选取3个参与方的秘密份额作为输入。这里选择 id 为 2,3,6的参与方进行秘密重建。
$(x_0,y_0)=(2,135);(x_1,y_1)=(3,219);(x_2,y_2)=(6,627);$
或者可以看出其实秘密
所以秘密就是$s=a_0=45$。
代码实现:
Python代码实现如下:
import random |