1. 引言
前序博客有:
- ECDSA VS Schnorr signature VS BLS signature 第三章 “3. BLS signature”
BLS signautre要求能够将(相同或者不同)curve上的P和Q两个点映射a number:
e
(
P
,
Q
)
↦
n
e(P,Q)\mapsto n
e(P,Q)↦n
同时,应满足如下属性:(使得secret number
x
x
x unreveal。)
e
(
x
×
P
,
Q
)
=
e
(
P
,
x
×
Q
)
e(x\times P,Q)=e(P,x\times Q)
e(x×P,Q)=e(P,x×Q)
更通用的表达为应具有如下属性:
e
(
a
×
P
,
b
×
Q
)
=
e
(
P
,
a
b
×
Q
)
=
e
(
a
b
×
P
,
Q
)
=
e
(
P
,
Q
)
(
a
b
)
e(a\times P,b\times Q)=e(P,ab\times Q)=e(ab\times P,Q)=e(P,Q)^{(ab)}
e(a×P,b×Q)=e(P,ab×Q)=e(ab×P,Q)=e(P,Q)(ab)
由于以上同态属性,使得BLS签名支持:
- signature aggregation:以非交互方式对同一消息生成聚合签名,以及对不同消息 m i m_i mi的不同签名进行聚合(即支持combine all signatures in the block)。
- key aggregation:m-of-n签名。
2. BLS签名
BLS签名机制要求a pairing friendly curve以及可对基域 F q \mathbb{F}_q Fq以及2个source group G 1 , G 2 \mathbb{G}_1,\mathbb{G}_2 G1,G2进行快速计算。 F r \mathbb{F}_r Fr为该curve的scalar域。
- EIP-196: Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128 中介绍了BN254 curve的addition和scalar multiplication运算。
- EIP-197: Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128中介绍了the check that a product of pairings is equal to one on BN254,即预编译合约验证 e ( a 1 , b 1 ) ∗ ⋯ ∗ e ( a k , b k ) = 1 e(a_1,b_1)* \cdots * e(a_k,b_k)=1 e(a1,b1)∗⋯∗e(ak,bk)=1。
- EIP-1108: Reduce alt_bn128 precompile gas costs 降低EIP-197和EIP-196中各运算的gas开销(由 约600万gas 降低为 约100万gas)。
- 在EVM底层支持模运算——基于BN254基域 F q \mathbb{F}_q Fq的addmod和mulmod运算。
回顾下适于EVM的BLS签名版本中有:
- generator G ∈ G 2 G\in \mathbb{G}_2 G∈G2
- 私钥 s k ∈ F r sk\in \mathbb{F}_r sk∈Fr
- 公钥 p k ∈ G 2 pk \in \mathbb{G}_2 pk∈G2
- 消息 m ∈ B ∗ m\in \mathbb{B}^* m∈B∗,为一组字节串
- Hash to curve算法 H : B ∗ → G 1 H: \mathbb{B}^*\rightarrow \mathbb{G}_1 H:B∗→G1
- BLS签名 σ ∈ G 1 \sigma \in \mathbb{G}_1 σ∈G1
BLS验签运算为:
e
(
σ
,
−
G
)
∗
e
(
H
(
m
)
,
p
k
)
=
1
e(\sigma ,-G)*e(H(m), pk)=1
e(σ,−G)∗e(H(m),pk)=1
当然,角色也可reverse,签名可为 σ ∈ G 2 \sigma \in \mathbb{G}_2 σ∈G2,但为何EVM的BLS签名版本中做如上 σ ∈ G 1 \sigma \in \mathbb{G}_1 σ∈G1等约定,原因有多个,关键原因在于:
- − G -G −G可预计算,且仅需要一次pairing乘积运算;
- 当采用BN254且签名 σ ∈ G 1 \sigma \in \mathbb{G}_1 σ∈G1时, H ( m ) H(m) H(m) Hash to curve算法相对更易高效计算。
2.1 Hash to curve算法
Hash to curve算法流程中包括:
- 1)hash to possible x x x坐标(为基域元素)
- 2)取平方根——借助curve方程式获得 y y y坐标
- 3)将获得的curve point
(
x
,
y
)
(x,y)
(x,y) 与 cofactor 相乘,以 由larger group point 获得 指定的prime group
G
1
\mathbb{G}_1
G1 point。
由于BN254 curve的cofactor为1,因此无需与cofactor相乘,其获得的 ( x , y ) ∈ G 1 (x,y)\in \mathbb{G}_1 (x,y)∈G1,hash to curve算法效率更高。
如BLS Signatures in Solidity中所讨论,可采用try-and-increment hash to curve算法(如上图所示) 或 Fouque-Tibouchi Hash to Curve 算法。Hubble项目合约中采用Fouque-Tibouchi Hash to Curve 算法。
若应用场景中支持中间aggregator,还可借助mapPointWithHelp 进一步优化其中昂贵的“sqrt”运算。
但是,若reverse到 G 2 \mathbb{G}_2 G2,执行以上运算将是昂贵的,因 G 2 \mathbb{G}_2 G2的cofactor约为254 bits,将其与某256-bit scalar相乘的开销约为400万gas,详细见https://github.com/musalbas/solidity-BN256G2所示。可借助endomorphisms——Efficient hash maps to G 2 \mathbb{G}_2 G2 on BLS curves的对scalar multiplication大幅优化,但gas开销仍将不低于100万。
3. 多重签名
如有一组validator set需协作对同一消息进行approve。
- public key aggregation:在注册时注意获取参与者的proofs-of-possession,可将所有公钥直接相加以获得public key aggregation。
- signature aggregation:简单相加即可。
由于签名属于 G 1 \mathbb{G}_1 G1效率更高,则公钥是属于 G 2 \mathbb{G}_2 G2。由于目前不存在 G 2 \mathbb{G}_2 G2的预编译加法运算,需在EVM中实现,根据https://github.com/musalbas/solidity-BN256G2,单次 G 2 \mathbb{G}_2 G2加法运算需约3万gas,而单次 G 2 \mathbb{G}_2 G2加法运算仅需约500 gas。
乐观情况下,大多数signer都参与了,仅有1到2个signer未参与,则需要从所有signer的fully aggregated public key中 减去 未参与signer的公钥,若签名足够频繁,这种移除操作也将是昂贵的。未参与signer越多,移除开销越大。
3.1 helped aggregation
既然 G 1 \mathbb{G}_1 G1上的加法运算很便宜,那么,可要求参与者在注册时,提供与其私钥 s k sk sk 对应的2个公钥:
- p k 2 = s k ⋅ G ∈ G 2 pk_2=sk\cdot G\in\mathbb{G}_2 pk2=sk⋅G∈G2,与原始公钥相同
- p k 1 = s k ⋅ H ∈ G 1 pk_1=sk\cdot H \in\mathbb{G}_1 pk1=sk⋅H∈G1,其中 H H H为 G 1 \mathbb{G}_1 G1的generator。这是新增加的公钥。
- BLS验签为: e ( − σ , G ) ∗ e ( H 2 ( p k 2 ) , p k 2 ) = 1 e(-\sigma, G)*e(H_2(pk_2), pk_2)=1 e(−σ,G)∗e(H2(pk2),pk2)=1,其中 H 2 H_2 H2为不同于之前 H H H的Hash to curve算法。如,其几乎与 H H H相同,但采用不同的domain。
- 在参与者注册时,检查: e ( p k 1 , G ) ∗ ( − H , p k 2 ) = 1 e(pk_1,G)*(-H,pk_2)=1 e(pk1,G)∗(−H,pk2)=1,确保 p k 1 , p k 2 pk_1,pk_2 pk1,pk2具有相同的私钥——基于B-KEA假设。
如The Power of Proofs-of-Possession: Securing Multiparty Signatures against Rogue-Key Attacks所述,BLS signature check为a proof-of-possession。
当submitter提交多重签名时,需包含:
- 签名本身
- 参与签名的参与者bitmap
- 包含 p k 2 pk_2 pk2 variants on G 2 \mathbb{G}_2 G2的aggregated公钥,如: a p k = p k 2 , A l i c e + p k 2 , B o b + p k 2 , C h a r l i e apk=pk_{2,Alice}+pk_{2,Bob}+pk_{2,Charlie} apk=pk2,Alice+pk2,Bob+pk2,Charlie
而合约自身会:
- 计算 p k 1 pk_1 pk1 variants on G 1 \mathbb{G}_1 G1的aggregated公钥,如: P 1 = p k 1 , A l i c e + p k 1 , B o b + p k 1 , C h a r l i e P_1=pk_{1,Alice}+pk_{1,Bob}+pk_{1,Charlie} P1=pk1,Alice+pk1,Bob+pk1,Charlie
- 检查 e ( P 1 , g ) ∗ e ( − H , a p k ) = 1 e(P_1,g)*e(-H,apk)=1 e(P1,g)∗e(−H,apk)=1。
合约会提供如下伪接口:
function verifySignature(bool[] signersBitmap, G2Element apk, G1Element signature)
其中:
- a p k apk apk:由链下计算,为对应 s i g n e r s B i t m a p signersBitmap signersBitmap中参与签名者的 p k 2 pk_2 pk2公钥之和。
- 从合约stoarge获取所有签名者 p k 1 pk_1 pk1聚合公钥,再减去 s i g n e r s B i t m a p signersBitmap signersBitmap中未参与签名者的 p k 1 pk_1 pk1公钥。【假设大多数签名者都将参与每次签名,则做减法操作比做加法操作可消耗更少的gas。】
这样,可高效聚合 G 1 \mathbb{G}_1 G1公钥,并验证在链下计算的 G 2 \mathbb{G}_2 G2公钥。
3.2 进一步优化
为避免引入额外的pairing check
e
(
p
k
1
,
G
)
∗
(
−
H
,
p
k
2
)
=
1
e(pk_1,G)*(-H,pk_2)=1
e(pk1,G)∗(−H,pk2)=1,可将其与现有的BLS验签方程结合:
引入随机
α
\alpha
α,借助Schwartz-Zippel lemma,将2个独立的pairing check方程式结合在一起,有:
e
(
σ
,
−
G
)
∗
e
(
H
(
m
)
,
a
p
k
)
∗
(
e
(
P
1
,
G
)
∗
e
(
−
H
,
a
p
k
)
)
α
=
1
e(\sigma, -G)*e(H(m),apk)*(e(P_1,G)*e(-H,apk))^{\alpha}=1
e(σ,−G)∗e(H(m),apk)∗(e(P1,G)∗e(−H,apk))α=1
借助pairing bilinearity属性,将
α
\alpha
α移到
G
1
\mathbb{G}_1
G1上,有:
e
(
σ
,
−
G
)
∗
e
(
H
(
m
)
,
a
p
k
)
∗
e
(
α
P
1
,
G
)
∗
e
(
−
α
H
,
a
p
k
)
=
1
e(\sigma, -G)*e(H(m),apk)*e(\alpha P_1,G)*e(-\alpha H,apk)=1
e(σ,−G)∗e(H(m),apk)∗e(αP1,G)∗e(−αH,apk)=1
借助pairing的结合属性,有:
e
(
σ
−
α
P
1
,
−
G
)
∗
e
(
H
(
m
)
−
α
H
,
a
p
k
)
=
1
e(\sigma-\alpha P_1,-G)*e(H(m)-\alpha H,apk)=1
e(σ−αP1,−G)∗e(H(m)−αH,apk)=1
根据https://gist.github.com/kobigurk/257c1783ddf556e330f31ed57febc1d9中的原型实现,hashing into α \alpha α以及2次scalar multiplication的开销约为1.6万gas,还存在进一步优化的空间。
3.3 结论
通过引入额外的元素,以及对参与方注册时的check,可获得更高效的链上BLS multisignature verification算法。聚合公钥的每次修改将引入小的gas开销,少量元素的hash仅需固定的便宜的gas开销,存在2次scalar multiplication,每个需6千gas开销。
参考资料
[1] Geometry团队2022年11月博客 优化EVM中的BLS多重签名
附录1 B-KEA是malleable的
若仅使用B-KEA,存在rogue-key攻击的问题。
假设Alice有公钥
A
1
=
a
H
,
A
2
=
a
G
A_1=aH,A_2=aG
A1=aH,A2=aG,满足
e
(
A
1
,
G
)
∗
e
(
−
H
,
A
2
)
=
1
e(A_1,G)*e(-H,A_2)=1
e(A1,G)∗e(−H,A2)=1。
Bob选择
B
1
=
X
1
−
A
1
,
B
2
=
X
2
−
A
2
B_1=X_1-A_1,B_2=X_2-A_2
B1=X1−A1,B2=X2−A2,其中
X
1
=
x
H
,
X
2
=
x
G
X_1=xH,X_2=xG
X1=xH,X2=xG,Bob声称
B
1
和
B
2
B_1和B_2
B1和B2为其公钥,但其并不知道相应的私钥,但仍满足
e
(
B
1
,
G
)
∗
e
(
−
H
,
B
2
)
=
1
e(B_1,G)*e(-H,B_2)=1
e(B1,G)∗e(−H,B2)=1。
若Bob可验证verification function的bitmap,提交其以 x x x的BLS签名(声称其来自于Bob和Alice双方),则多签验证可通过,因 A 1 + B 1 = A 1 + X 1 − A 1 = X 1 A_1+B_1=A_1+X_1-A_1=X_1 A1+B1=A1+X1−A1=X1。
附录2 批量注册
在3.2节中展示了如何在验签环节批量合并验证方程式,此处也可进行批量注册检查。
注册时需验证以下2个方程式:
e
(
−
σ
,
G
)
∗
e
(
H
2
(
p
k
2
)
,
p
k
2
)
=
1
e(-\sigma, G)*e(H_2(pk_2), pk_2)=1
e(−σ,G)∗e(H2(pk2),pk2)=1
e
(
p
k
1
,
G
)
∗
(
−
H
,
p
k
2
)
=
1
e(pk_1,G)*(-H,pk_2)=1
e(pk1,G)∗(−H,pk2)=1
引入随机数
α
=
h
a
s
h
(
σ
,
m
,
p
k
1
,
p
k
2
)
\alpha=hash(\sigma,m,pk_1,pk_2)
α=hash(σ,m,pk1,pk2),将以上2个方程式合并为:
e
(
−
σ
,
G
)
∗
e
(
H
2
(
p
k
2
)
,
p
k
2
)
∗
(
e
(
p
k
1
,
G
)
∗
(
−
H
,
p
k
2
)
)
α
=
1
e(-\sigma, G)*e(H_2(pk_2), pk_2)*(e(pk_1,G)*(-H,pk_2))^{\alpha}=1
e(−σ,G)∗e(H2(pk2),pk2)∗(e(pk1,G)∗(−H,pk2))α=1
从而有:
e
(
−
σ
−
α
⋅
p
k
1
,
G
)
∗
e
(
H
2
(
p
k
2
)
−
α
H
,
p
k
2
)
=
1
e(-\sigma-\alpha\cdot pk_1, G)*e(H_2(pk_2)-\alpha H, pk_2)=1
e(−σ−α⋅pk1,G)∗e(H2(pk2)−αH,pk2)=1