简介
基本原理
ECC本质上是使用离散对数问题的理论上不可解来实现。即G为EC上的一个点,那么在知道x*G的情况下,想要求解x在当前的计算机架构下不可行。无论是ECDSA、Schnorr还是BLS本质上就是通过离散对数问题不可解来隐藏信息。因为离散对数问题的不可解,所以可以将x作为一个秘密,用x*G = X表示这个秘密的唯一标识。
如何在不公开秘密的前提下证明自己知道该秘密?一个可行的方法就是对该秘密x进行运算操作,并给出运算的结果,但是必须保证该运算是一个trapdoor function 。而离散对数问题恰好就是一个trapdoor function。
关于什么是trapdoor function,请参考https://en.wikipedia.org/wiki/Trapdoor_function
假设对x的运算为f(x), 运算后的结果必须是一个与x*G = X有关的函数
f(x)*G = F(X)
一个简单的方式就是
f(x)=x+r,其中r为一个随机数,则有
f(x)*G = (x+r)*G = x*G + r*G = X + r*G
因此,如果一个人能够提供(x+r) 以及r*G,那么就说明这个人知道x
签名算法则在此基础上进行修改,即尝试将消息的摘要放进到操作f(x)中
例如
f(x) = x*H(m) + r
那么
f(x)*G = x*H(m)*G + r*G = H(m)*X + r*G
因此针对消息m,H(m)为确定值,如果一个人能够提供
(R, s) =(r*G, x*H(m) + r)
且满足
s*G = H(m)*G + R
那么就说明这个人知道x且知道m。
ECDSA
f(x) = (H(m) + k*x) / r,其中k为r*G的横坐标
签名(k,s) = (r*G的横坐标, (H(m) + k*x) / r)
f(x)*G = (H(m) + k*x) / r * G 两边乘以r
=> f(x)*G = H(m)*G + k*x*G = H(m)*G + k*X = F(X)
Schnorr
f(x) = H(m)*x + r
签名(R, s) = (r*G, H(m)*x + r)
f(x)*G = H(m)*x*G + r*G = H(m)*X + R = F(X)
可以看到ECDSA和Schnorr使用x*G = X的逆运算的方式是一致的,则在确定G的前提下,通过操作x本身来实现秘密的证明。唯一不一样的是Schnorr中f(x)是线性函数,而ECDSA中不是线性函数(因为每次签名,r必须使用不一样的值,否则会被攻击,可参考https://bitcointechtalk.com/scaling-bitcoin-schnorr-signatures-abe3b5c275d1)
BLS的出发点是,能不能通过操作G的方式来实现秘密的证明?也就是找到一个R,使得
f(R) = F(X)
先简单了解两个概念
hash_to_point
在BLS中使用的Hash算法,与ECDSA和Schnorr中的Hash算法有所区别,本质上就是将需要签名的消息hash之后成为EC上的点。
Curves pairing(bilinear map)
假设存在函数e(P, Q) → n,其中P, Q都是EC上的一个点,n为一个标量值,那么所谓Paring是指映射e满足以下的性质:
e(xP, Q) → e(P, xQ)
e(aP, bQ) = e(P, abQ) = e(abP, Q) = e(P, Q)^(ab)
BLS方案
Signature generation
S = pk * H(m)
Signature verification
provide S = pk * H(m)
check e(G, S) =?e(P, H(m))
e(G, S) = e(G, pkH(m)) = e(pkG, H(m)) = e(P, H(m))
Signature aggregation
S = S1+S2+…+S1000
verification:
***e(G, S) = e(P1, H(m1))⋅e(P2, H(m2))⋅…⋅e(P1000, H(m1000))
e(G, S) = e(G, S1+S2+…+S1000) = e(G, S1)⋅e(G, S2)⋅…⋅e(G, S1000) = e(G, pk1×H(m1))⋅…⋅e(G, pk1000×H(m1000)) = e(pk1×G, H(m1))⋅…⋅e(pk1000×G, H(m1000)) = e(P1, H(m1))⋅e(P2, H(m2))⋅…⋅e(P1000, H(m1000))
特点:
- 可以把针对不同消息mi的多个签名聚合成1个
- 签名由1000个子签名合成,在校验签名时,仍然要做1001次pairing
Key aggregation && n-of-n signature
S=S1+S2+S3
P=P1+P2+P3
e(G, S) = e(P, H(m))
e(G, S) = e(G, S1+S2+S3) = e(G, (pk1+pk2+pk3)×H(m)) = e((pk1+pk2+pk3)×G, H(m)) = e(P1+P2+P3, H(m)) = e(P, H(m))
添加非线性来防止rogue key attack
S = a1×S1+a2×S2+a3×S3
P = a1×P1+a2×P2+a3×P3
ai = hash(Pi, {P1,P2,P3})
ai = hash(Pi||P1||P2||P3)
m-of-n signature
setup phase
P = a1×P1+a2×P2+a3×P3, ai = hash(Pi, {P1,P2,P3})
MKi = (a1⋅pk1)×H(P, i)+(a2⋅pk2)×H(P, i)+(a3⋅pk3)×H(P, i)
e(G, MKi)=e(P, H(P,i))
Signing
S1 = pk1×H(P, m)+MK1***, ***S3=pk3×H(P, m)+MK3
(S’, P’) = (S1+S3, P1+P3)
e(G, S’) = e(P’, H(P, m))⋅e(P, H(P, 1)+H(P, 3))
e(G, S’) = e(G, S1+S3)=e(G, pk1×H(P, m)+pk3×H(P, m)+MK1+MK3) =e(G, pk1×H(P, m)+pk3×H(P, m))⋅e(G, MK1+MK3)=e(pk1×G+pk3×G, H(P, m))⋅e(P, H(P, 1)+H(P, 3))=e(P’, H(P, m))⋅e(P, H(P, 1)+H(P, 3))
BLS针对rogue key attacks的不同方案
BLS中签名S=pk*H(m),所以如果是对同一个消息m进行聚合签名,容易被攻击,过程如下:
假设有聚合签名有三方,公私钥分别是(pk1, P1), (pk2,P2), (pk3, P3),其中P1,P2,P3都是公开的。
那么参与方2就可以声称自己的公钥是(P2-P1-P3)
在针对同一个m的聚合签名中,最终校验的公式为
e(S, G) = e(H(m), P)
其中S = S1 + S2 + S3,Si = pki * H(m)
P = P1 + P2 + P3
当P2 - P1 - P3 ⇒ P2时,P = P2
那么此时参与方2就能够构建任意消息mm的签名,因为
e(pk2*H(mm), G) = e(H(mm), P2) = e(H(mm), P) = e(H(mm), P1)*e(H(mm), P2-P1-P3)*e(H(mm), P3)
Basic scheme
要求聚合签名中不能有任意两个消息是一样的
Message augmentation
在对消息进行签名时,将公钥与消息拼接起来,这样就能确保H(m || Pi)是不一样的,即使参与方2声称自己的公钥是P2-P1-P3,也无法再伪造签名,因为
e(H(m||P1), P1)*e(H(m||P2-P1-P3), P2-P1-P3)*e(H(m||P3), P3) != e(H(m||P2),P2)
Proof of possession
用私钥对公钥的hash进行签名生成proof of possession,即
S = pk*H(P)
如果参与方2声称自己的公钥是P2-P1-P3,那么参与方必须知道pk2-pk1-pk3才能构造出proof。
应用情况
EIP2537
EIP-2537: Precompile for BLS12-381 curve operations
BLS、Schnorr Signature、ECDSA对比
是否支持聚合签名 | 签名是否需要生成随机数 | 聚合签名是否需要交互 | 是否支持讲一个块中所有交易的签名聚合成一个 | 签名校验效率 | |
---|---|---|---|---|---|
ECDSA | 否 | 是 | 无 | 否 | |
Schnorr | 是 | 是 | 是 | 否 | 单个签名不需要计算1/r,效率更高,聚合后的签名比单独校验n个ECDSA签名要高 |
BLS | 是 | 否 | 否 | 是 | 复杂度比ECDSA高一个数量级,尤其是对n个不同消息的签名的聚合,仍然要做n+1次pairing运算 |
BLS使用情况
ethereum
release1.12已经实现了BLS12_381,预编译合约也实现,当前还没上线主网。
Chia
引用的是blspy
Metadata-Version: 2.1
Name: blspy
Version: 2.0.2
Summary: BLS signatures in c++ (python bindings)
Home-page: <https://github.com/Chia-Network/bls-signatures>
Author: Mariano Sorgente
Author-email: mariano@chia.net
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: wheel
该包是基于https://github.com/Chia-Network/bls-signatures实现的package,底层使用的是https://github.com/supranational/blst,blst是c实现的bls12-381开源项目,实现了IETF标准中的接口(主要是sign,verify,aggreate,aggregate_verify)。在Chia中主要是使用n-of-n aggregate方式来将区块中将交易的签名聚合成一个
Filecoin
基于rust实现的BLS,rust编译成.h和.o文件后,使用cgo调用。但是只使用了最简单的bls签名和验签,没有使用aggregate和verify函数。
reference
BLS协议解析
BLS signatures: better than Schnorr
BLS标准, irtf
BLS论文
https://www.iacr.org/archive/asiacrypt2001/22480516.pdf
https://eprint.iacr.org/2002/088.pdf