MPC与TSS
多方安全计算MPC是一种前沿的分布式加密计算技术的集合,通过多个参与者进行计算,在暴露一部分必要信息的同时隐藏另一部分关进信息,并求得一个公开的结果,从而保证运算结果的安全性或隐私性。
门限签名(Threshold Signature Scheme, TSS)是一种MPC技术,在加密货币行业中目前的主要应用场景为钱包的私钥和签名安全,也即多个参与者共同生成私钥,每个人持有其中的一个片段。其主要性质为:
- 没有任何人知道完整的私钥,也即私钥永远不会出现。
- 所有参与者共同计算出完整私钥所对应的公钥。
-
需要m个参与者(m≤n)即可产生对应完整私钥的签名。
这几个性质乍一听是非常反直觉且互相矛盾的。这也正是TSS方案的高明和有趣之处。本文将介绍TSS方案中目前应用最广泛且最成熟的GG20算法,由Rosario Gennaro(纽约市立学院教授,Protocol Labs的密码学家) 和 Steven Goldfeder(普林斯顿大学的密码学者,Arbitrum的CEO)在2020年提出。
GG20概要
GG20并不是一个空穴来风横空出世的方案,其前身为2018年也是由二位作者提出的GG18,GG20对其进行了效率和安全性的优化。在GG20之前也有许多TSS方案,但在理论或实际使用中有各种各样的问题,GG20结合了大量前人的工作成果与自身灵感,得出了一种适用于工程实践的TSS方案,具有如下优点:
- 高效率,运算快,通讯复杂度低。
- Dealerless,没有中心化的dealer用于分派秘密或协调组织。
- 高安全性假设,基于不诚实多数的恶意敌手模型。
GG20使用了下列密码学或数学手段:
- 分布式密钥生成
- Paillier同态加密
- Shamir秘密共享
- Feldman VSS
- MtA转换
- 零知识证明
- 拉格朗日插值
- 不可延展二义性承诺
本文是大众向的科普文章,对所有概念都会进行简单的复盘,且会尽可能减少专业术语或公式以及次要内容。如,GG20中由安全引申出的复杂的验证步骤将会被省略,只关心业务主线。并且我们不仅关注是什么,更关注背后的为什么,因此行文将是启发式的。
现在我们进入正题。显然,一个TSS方案包含两个主要模块:门限密钥生成和门限签名。前者负责去中心化地为每个参与者生成互不知晓的私钥碎片,后者用这些私钥碎片签名出签名碎片,然后再拼接成对应完整私钥的完整签名。
门限密钥生成
先设想一下如何分布式地保存私钥。私钥本质上是自然数,假设我的私钥是50,我可以拆分成10+25+15三个私钥片段分别给三个不同的人保管。上述方案对TSS而言有三个问题:
- 三个人必须同时出现,少一方都无法恢复这个私钥,有严重的单点故障,不符合门限的需求。
- 『我』是一个中心化的实体,不符合dealerless的要求。
- 完整的私钥在分发和重构时出现了两次。不符合完整的私钥永不出现这一性质。
所以,如果要实现一个2-of-3(三人持私钥片段,任意两人即可签名)的门限密钥生成方案,先让三人Pᵢ (i∈[1,3])
每个人各自生成自己的私钥片段uᵢ
并秘密地保存起来。由于门限要求,那么这三人所持有的私钥片段之间必须有间接的数学联系,以在缺少一方的情况下也有恢复完整私钥的能力。
注意,这里所说的具有『恢复完整私钥的能力』只是一种『能力』,并非要实施『恢复完整私钥』这个行为。该能力实际上等价于『可用签名碎片拼出对应完整私钥的签名的能力』,后者对应的行为才是我们最终要实施的。所以在下文中提到『恢复完整的私钥』时,仅仅指的是这种能力,或者在思维实验中实施该行为,而非要在现实的TSS方案中进行。
SSS与『间接的数学联系』
假设私钥碎片为u₁=20, u₂=40, u₃=80
。如果允许中心化的dealer和完整的私钥出现,那每个人把私钥uᵢ
发给dealer,他就可以计算出完整私钥u=140
后用Shamir秘密共享(SSS)方案:把完整私钥拆碎后再分配,在拆分和合成过程中这些私钥碎片之间会用拉格朗日多项式产生间接的数学联系。
SSS的秘密分发
现有门限参数m-of-n,dealer对秘密u
进行SSS:
- 先构造最高次为
t = m - 1
的主多项式F(x)
- 其中多项式系数
a₁...aₜ
都是dealer随机选择的 - 常量
u
就是要共享的秘密,有F(0) = u
- Dealer把
F(i)
分享给Pᵢ
(i∈[1,n]
),Pᵢ
记录下坐标点(i,F(i))
。Dealer销毁主多项式。分享结束。注意,除了dealer每个人只知道自己的值F(i)
,但并不知道主多项式F(x)
的具体式子。
具体到我们的例子中,即
F(x) = 140 + 5x
, P₁得到F(1)=145
, P₂得到F(2)=150
, P₃得到F(3)=155
.
SSS的秘密重构
- 确定参与重构的人数不得少于
m
,记∀重构者编号i
的集合为Φ
- 每个参与者
Pᵢ
公布自己的坐标点(i,F(i))
- 计算每个人的拉格朗日基函数
lᵢ(x)
并得到拉格朗日插值多项式L(x)
- 展开
L(x)
后其常数项就是秘密
具体到我们的例子中,秘密被分片到了三个人手中,但只需要两个人即可重构。比如,P₁和P₂进行重构,我们得到两个坐标点(1,145)和(2,150)
,使用拉格朗日插值法得:
可以看到常数项
140
已经展现了出来,也即我们要恢复的秘密。
拉格朗日插值法本质是对若干个随意的数据点拟合出一条合适的多项式曲线。纵观上述过程,我们先巧妙地构造了一个x=0
时值为秘密
的多项式,然后利用m个点可以唯一确定一个最高为m-1次的多项式
的性质,将秘密沿着多项式分发给每个参与者。我们选用的是2-of-3作为讲解,也即m=2,n=3
,所以例子中的多项式是一个非常简单的一次函数。我们可以在这个函数上任意增加点,也即秘密共享者,而只需要两个点就可以重构出整个一次函数并取得秘密,少于两个则不行,也即实现了门限的需求。
上述过程即SSS的核心原理。实际的SSS为了安全性还使用了素数的模运算和费马小定理等,这里按下不表。
去除Dealer
虽然上述过程看起来很有意思,不过别忘了它是有中心化Dealer参与的,私钥也现身了两次,不符合我们的需求。
但我们可以通过每个人都对自己+其余人
进行SSS的方式,分享出自己的秘密uᵢ
,在不出现u
的情况下拆分成新的秘密碎片χᵢ
,从而满足我们的需求。
以P₁
为例,他自己当delaer,在P₁
, P₂
,P₃
间进行2-of-3共享。这里和上面不太一样的是,dealer自己也是被共享者。
由于u₁=20
,则
F₁(x) = 20 + 2x
, P₁得到F₁(1)=22
, P₂得到F₁(2)=24
, P₃得到F₁(3)=26
.
由于u₂=40
,则
F₂(x) = 40 + 6x
, P₁得到F₂(1)=46
, P₂得到F₂(2)=52
, P₃得到F₂(3)=58
.
由于u₃=80
,则
F₃(x) = 80 + 10x
, P₁得到F₃(1)=90
, P₂得到F₃(2)=100
, P₃得到F₃(3)=110
.
∀Pᵢ
分别计算自己新生成的秘密碎片χᵢ
并私密保存:
χ₁=F₁(1)+F₂(1)+F₃(1)=158
,
χ₂=F₁(2)+F₂(2)+F₃(2)=176
,
χ₃=F₁(3)+F₂(3)+F₃(3)=194
.
验证一下:用拉格朗日插值法可得出L(x)=18x+140
,我们的完整私钥u=140
依然成立。当然,再次提醒,这个验证步骤我们实际是不可能进行的,私钥u
和L(x)
永远不会有人知道。
在实操中,GG20并不使用SSS,而是使用其升级版Feldman VSS,在不暴露多项式的情况下确定每个人的多项式运算不存在作弊行为。这里不进行详解。
私钥解决了,下面来解决公钥。
公钥计算
上面我们已经成功将碎片uᵢ
重新划分为新的私钥碎片χᵢ
。后续为了方便书写我们将用x
表示私钥及其分片xᵢ
,用y
表示公钥。
由于GG20中使用的G-DSA支持DSA(离散对数数字签名方案)和ECDSA(椭圆曲线数字签名方案),可以生成这两种方案的公钥:
y_DSA = gˣ
y_ECDSA = xG
g和G分别为循环群和椭圆曲线的生成元,我们这里不需要理解这个具体是什么概念,只需要知道不可能用gˣ
或xG
的值来反推出x
即可。
因为我们不能直接计算x=∑xᵢ
(不成立)或者u=∑uᵢ
(禁止暴露),所以只需∀Pᵢ
计算自己的g^(uᵢ)
或uᵢG
并公布然后进行拼接,最后得到公钥:
至此,公钥私钥都已解决,下面研究签名的问题。
门限签名
看下GG20中的G-DSA是如何定义签名和验证过程的。
签名
- 计算
m = H(M)
,其中M为消息,H为哈希函数,m为哈希值 - 选择随机数
k
- 计算
R = gᵏ⁻¹
和r = H'(R)
,其中H’并不是哈希函数,是一个简单的处理函数,对DSA和ECDSA略有不同 - 计算
s = k(m + xr) mod q
,其中q
为循环群的阶 - 输出签名
σ = (r, s)
验证
- 输入消息M,签名σ 以及公钥y
- 检查r, s值的范围
- 计算
R'= g^(ms⁻¹ mod q)·y^(rs⁻¹ mod q)
- 当且仅当
H'(R') = r
,验证通过
显然,验证过程跟分布式生成签名没有关系,我们只看如何不拼接出完整私钥的情况下分布式地生成签名(r,s)
。
首先要注意一点,随机数k
的生成也像私钥一样是分布式且秘密的,每个人都只掌握自己的kᵢ
,否则会有严重的安全问题。举个例子,若所有人的kᵢ
都不小心被恶意签名者盗取,他完全可以最后再提交自己的kᵢ
,制造一个之前使用过的随机数,构建Fault Attack,恢复出完整私钥。另外,即使没有安全问题,直接拿到k
对我们也没有任何意义,因为我们不可能在s = k(m + xr)
中直接使用k
,那意味着直接暴露私钥x
。
求R和r
另外我们也注意到r=H'(R), R=gᵏ⁻¹
的取值和k
也有关,所以r和s都只能迂回智取,因此我们再引入一个和kᵢ
一样需要保密的随机数γᵢ
。我们先用γ
给R
做一下变形:
我们变形的其中一部分为
g^γᵢ
,它是可以公开的,因为γᵢ
被隐藏了起来,但在指数上还有个kγ
需要解决。
虽然我们不能按照kγ = ∑kᵢ·∑γᵢ
直接运算,但不妨展开这个式子看看。我们还是让P₁
, P₂
出场:
kγ = ∑kᵢ·∑γᵢ = (k₁γ₁ + k₂γ₁) + (k₂γ₂ + k₁γ₂)
考察第一个括号内的式子(k₁γ₁ + k₂γ₁)
,让P₁
计算该式,那么他只能计算到k₁γ₁
,因为P₂
不会给他提供k₂
。对于P₂
那边的(k₂γ₂ + k₁γ₂)
也是同理的。
对第一个括号内的式子而言(第二个同理),如果我们能有一种交换协议,能让P₁
为P₂
提供γ₁
,P₂
为P₁
提供k₂
,但两个人又互相不知道双方提供的值是什么,还却能分别为两人生成另外两个新的秘密的数,那我们就能实现这个对等的交换共享:
k₂γ₁ = A + B
,k₁γ₂ = C + D
,其中P₁
得到了B
和C
,P₂
得到了A
和D
。
每个Pᵢ
构造一个可公开的中间变量δᵢ
,则δ₁ = (k₁γ₁ + B + C)
, δ₂ = (k₂γ₂ + A + D)
,我们发现
这样就求出了kγ
,但是这种交换协议该怎么实现呢?
MtA转换和Paillier同态加密
我们把上面那种转换称为MtA(Multiplicative to Additive,乘转加)共享转换,其原理是同态加密,用Paillier加密算法实现。
同态加密:如果一种加密算法E,能够实现E(X)+E(Y)=E(X+Y)
,我们就称呼其具有加法同态,Paillier就是一种加法同态加密算法。乘法同态同理。
MtA:Alice和Bob二人分别持有对秘密ξ = ab mod q
的乘法分片a和b,这两个分片也是要保密的。MtA在保密a和b的前提下,将a和b转化为加法分片α和β,使得α + β = ξ = ab mod q
。
- Alice先构建自己的Paillier公私钥对,公布公钥后A后就可以让Bob使用
E_A
加密 - 先将a的加密
cA= E_A(a)
发送给Bob。由于是密文,Bob无从知晓其内容。 - 但由于同态加密性质,Bob却可以对密文cA进行运算生成新的密文cB:
cB = b × cA + E_A(β') = E_A(ab + β')
发送给Alice,其中β’
是一个随机数 - Bob设置自己的加法分片
β = -β' mod q
- Alice解密
cB
,内容记为α’
,并设置自己的加法分片α = α’ mod q
MtA协议完成。实际上为了保障可靠性,还需要用到ZK和Range Proof等手段进行检查,此处省略。
如果不使用MtA,用其他手段直接运用乘法态也是可以的,似乎可以不用如此迂回繁琐。但这么做会有其他实用性问题,直接影响整个TSS协议的实用性,具体问题这里就不详解了。所以MtA是很关键的一步。
由于MtA是双方互换,在实际使用中我们的签名者可能有若干个,需要进行多轮的两两互动,这种两两互动可以通式记作:
-
Pᵢ
和Pⱼ
进行MtA,则Pᵢ
收到αᵢⱼ
,Pⱼ
收到βᵢⱼ
-
kᵢγⱼ= αᵢⱼ+ βᵢⱼ
,引入中间变量δᵢ
- 计算每个人的
δᵢ
并公布,再公布g^γᵢ
即可求出R和r = H'(R)
:
求S
重新观察一下s = k(m + xr)
(省略了mod q),可变换为s = km + kxr
,其中r
我们已经在上一步有了。但这里有出现了一个类似kγ
的不可能直接计算的乘法量kx
,其中x
是私钥。
那么我们对kx
如法炮制也使用MtA就解决问题了。但仔细想一下,我们上面能够对kγ
使用MtA有一个重要前提,即k = ∑kᵢ ∧ γ = ∑γᵢ
。因为k和γ我们就是这么定义的,所以它自然就符合分片之和等于总和(但还请注意之前强调的,这是思想实验,现实我们不会直接相加秘密值)。
但在kx
的x
中,就不符合这个条件。因为xᵢ
是我们在做了SSS分享后的结果,x₁=158,x₂=176,x₃=194
。具有了门限能力,但直接相加没有意义,不论你加哪两个人的秘密都无法得到总私钥140
。
而分享之前的三个人之和u₁=20,u₂=40,u₃=80
才等于140
。但现在因为我们是在做门限签名,只有P₁
和P₂
两个人在场。
在签名参与者中重新生成私钥碎片
我们要继续利用拉格朗日多项式系数的性质,将一个m-of-n秘密分享转化为当下要用的m-of-m+1分享。
我们再回忆下上面的拉格朗日多项式,为了避免函数自变量x
和私钥x
混淆,这里将函数自变量改为了z
:
我们可以将私钥片xᵢ
转换为私钥片wᵢ
。可以看到,wᵢ
可以由Pᵢ
独立运算,不需要其他复杂的互动流程,x = w = ∑wᵢ
。验证一下:
w₁ = 158×(2-0) = 316
,
w₂ = 176×(0-1) = -176
,
w₁ + w₂ = 140
.
显然,我们将xᵢ
转换为wᵢ
就可以解决kx
的MtA问题。
对kw ( w = x )
我们继续使用和kγ
一样的处理方式:
-
Pᵢ
和Pⱼ
进行MtA,则Pᵢ
收到μᵢⱼ
,Pⱼ
收到νᵢⱼ
-
kᵢwⱼ= μᵢⱼ+ νᵢⱼ
,并引入中间变量σᵢ
- 计算每个人的
sᵢ
,然后公布sᵢ
即可求出s
至此,(r,s)都已经取得,我们已经完成了G-DSA的门限签名。
总结
- GG20 TSS方案分为门限密钥生成和门限签名两部分。
- 密钥生成部分,使用了拉格朗日插值法和多轮SSS等技巧,去中心化地构建了密钥碎片之间的门限联系,并生成了公钥。
- 签名部分,使用了拉格朗日系数的性质将(t,n)分享映射为(t,t+1)分享,并使用MtA将乘法秘密转化为加法秘密,将不可直接公开的变量转换为可公开运算的变量,最终分布式地求出了签名。
- 过程中我们省略了不可延展二义性承诺、零知识证明、Feldman VSS、Range Proof等技术手段。它们会保证协议的正确性,如有恶意行为,则程序终止,并能明确指出是哪位参与者是恶意的。
- GG20是在大量前人的研究工作基础上实现的,这些研究的时间跨度达到十数年,每一个展开都不会少于本文的篇幅。我们习惯了平铺直叙地用寥寥数语概括各种密码学方案和其应用场景,在我们稀松平常的描述中它们听起来似乎很简单。但背后实际上是海量的密码学和数学方法以及密码学家十几年如一日的钻研和积累。