一句话版本
把秘密藏在一个 k−1 次多项式的常数项 f(0) 里,发给每个人多项式上的一个点 (i,f(i))。
任意 k 个点可以用拉格朗日插值唯一确定多项式,从而还原秘密;少于 k 个点时,秘密的每一个可能值都同样可能,一点信息都不泄露。
全文分三层:
- 通俗理解:两点确定一条直线
- 实际用处:钱包备份、MPC 钱包、门限签名、DNSSEC 根密钥
- 数学原理:有限域上的多项式、拉格朗日插值、完美安全性,附手算例子
第一层:通俗理解
1.1 为什么要"拆"私钥
一把比特币私钥如果只存一份:
多存几份能防丢,却让被偷的风险翻倍。我们想要的是:拆成 5 份,分给 5 个人(或 5 个地方),任意 3 份凑在一起才能还原;任意 2 份凑在一起一点用都没有。这叫 (3,5) 门限方案。
1.2 两点确定一条直线
先看最简单的 (2,n) 方案:
- 把秘密 S 画在 y 轴上,即点 (0,S);
- 过这个点随便画一条(随机斜率的)直线;
- 在直线上取 x=1,2,…,n 处的点,每人发一个。
任意两个人把点拿出来,两点确定一条直线,延长到 y 轴就看到了 S。但只有一个点的人,过这个点的直线有无数条,与 y 轴的交点可以是任何值,所以完全猜不到 S。
要门限为 3,就把直线换成抛物线(三点确定一条抛物线);门限为 k,就用 k−1 次多项式。
1.3 和 RS 纠错码是一回事
Reed–Solomon 纠错码的做法是:把数据当作多项式系数,发送多项式在多个点上的值,丢掉一些点也能插值还原。Shamir 秘密分享用的是同一个代值映射,只是关注点不同:纠错码关心"丢了能补回来",秘密分享还额外关心"点不够时什么都看不出"。
第二层:实际用处
| 场景 |
怎么用 |
| 助记词分片备份(SLIP-39,Trezor 等硬件钱包) |
把钱包种子拆成若干份助记词,比如"5 份里任意 3 份" |
| 企业 / 交易所冷钱包 |
私钥分给多个高管或多个保险柜,防止单人作恶或单点丢失 |
| MPC 钱包与门限签名 |
更进一步:私钥从来不在任何一处完整出现,各方用自己的份额协同算出签名(如 FROST、GG20 协议) |
| DNSSEC 根密钥 |
互联网根区签名密钥的恢复凭据分给全球多位受信任社区代表保管,需要多人到场 |
| HashiCorp Vault |
解封主密钥默认拆成 5 份、门限 3 |
和多签的区别
比特币多签(multisig)是链上规定"需要 3 个不同私钥的签名",规则公开可见。门限签名是链下用秘密分享,最后只产生一个普通签名,链上看起来和单人钱包一样,更省手续费、更隐私。
朴素 Shamir 的两个弱点
- 还原的那一刻,完整秘密会出现在某台机器上,这台机器就成了攻击目标。MPC 钱包的意义就在于连这一刻都避免。
- 如果发份额的人(dealer)作弊,发了不一致的份额,接收者发现不了。可验证秘密分享(Feldman / Pedersen VSS)给每个系数附上一个承诺来解决这个问题。
第三层:数学原理
3.1 在有限域里做
实数上的多项式会泄露信息(比如份额的大小能暗示秘密的范围),所以一律在有限域 Fp 上做,p 是一个比秘密大的素数。
分发:秘密 S∈Fp,门限 k。随机选 a1,…,ak−1∈Fp,令
f(x)=S+a1x+a2x2+⋯+ak−1xk−1,
第 i 个人拿到份额 (i,f(i)),i=1,…,n。
3.2 为什么 k 个点能唯一确定多项式
域上一个非零的、次数不超过 k−1 的多项式最多有 k−1 个根(抽象代数:F[x] 是整环,因式定理)。如果两个次数 ≤k−1 的多项式在 k 个点上取值相同,它们的差有 k 个根,只能是零多项式。所以唯一。
3.3 拉格朗日插值
给定 k 个点 (xj,yj),构造
Lj(x)=m=j∏xj−xmx−xm,
它在 xj 处等于 1,在其他 xm 处等于 0。于是 f(x)=∑jyjLj(x)。我们只需要常数项:
S=f(0)=j∑yjLj(0),Lj(0)=m=j∏xj−xm−xm.
注意 S 是份额的线性组合。这一点很关键:门限签名里,各方不用交出份额,只要各自算出"份额 ×Lj(0)"这一部分,再在指数或椭圆曲线点上相加即可。
3.4 为什么 k−1 个份额毫无信息
固定任意 k−1 个份额。对秘密的每一个候选值 S′∈Fp,加上点 (0,S′) 一共 k 个点,恰好唯一确定一个多项式。所以每个 S′ 都对应同样多(恰好一种)的系数选法,而系数是均匀随机选的,于是每个 S′ 的概率都是 1/p。
这叫信息论安全(完美安全):不依赖任何计算难题,算力再强、有量子计算机也没用。和一次一密的道理相同。
3.5 手算例子
(3,5) 方案,F13
秘密 S=7,随机选 a1=3,a2=5:
f(x)=7+3x+5x2(mod13).
五个份额:
| i |
f(i) 计算 |
份额 |
| 1 |
7+3+5=15 |
(1,2) |
| 2 |
7+6+20=33 |
(2,7) |
| 3 |
7+9+45=61 |
(3,9) |
| 4 |
7+12+80=99 |
(4,8) |
| 5 |
7+15+125=147 |
(5,4) |
用第 1、3、5 份还原:
- L1(0)=(1−3)(1−5)(−3)(−5)=815。15≡2,8−1≡5(8⋅5=40≡1),所以 L1(0)=10
- L3(0)=(3−1)(3−5)(−1)(−5)=−45。−4≡9,9−1≡3,所以 L3(0)=15≡2
- L5(0)=(5−1)(5−3)(−1)(−3)=83=3⋅5=15≡2
S=2⋅10+9⋅2+4⋅2=46≡7(mod13).
还原出 7。(已用 Python 验算。)
总结
| 层次 |
要点 |
| 直觉 |
k 个点确定 k−1 次多项式,秘密在 y 轴截距上 |
| 代数 |
域上多项式根的个数有上限;拉格朗日插值;秘密是份额的线性组合 |
| 安全 |
少于 k 份时信息论安全,量子计算机也无能为力 |
| 工程 |
钱包备份、MPC 钱包、门限签名;需要防 dealer 作弊(VSS) |