BLS签名算法( 二 )


值得注意的是,配对函数中不能使用任何椭圆曲线(特别是比特币的 secp256k1 椭圆曲线) 。我们必须使用非常特殊的曲线(通常出自易于配对的曲线簇),才能保证函数的效率和安全 。
三、BLS签名方案现在终于能进入正题啦!
下面用 pk 表示私钥 ,  P 表示公钥 ,  m 表示待签名的消息 。其中 P = pk×G.
3.1 签名【BLS签名算法】① 对消息m 进行曲线哈希得到H(m).
② 使用私钥进行签名 。将刚刚得到的结果乘以私钥 。
S = pk × H(m)
3.2 验证签名在验证签名的时候,使用公钥 P 进行验证 。验证过程如下:
e ( P , H(m) ) = e ( G , S )
3.3 原理下面证明 e ( P , H(m) ) = e ( G , S ) 该等式成立 。
已知:P = pk×G,e ( xP , Q ) = e ( P , xQ ) .
e ( P , H(m) ) = e (  pk ×  G, H(m) ) =  e (  G , pk × H(m) ) = e (  G ,  S )
下图能够很直观的表示 。BLS 签名验证,我们只需验证 公钥和消息的哈希值(曲线上两个点)与曲线生成点和签名(曲线上另两个点)是否映射到同一个数(若是则说明这是一个有效的 BLS 签名) 。

BLS签名算法

文章插图
四、签名聚合前面提到BLS签名算法可以实现签名聚合,下面就来介绍这个非常棒的特性 。
现在假设在区块链的场景下,有一个区块有1000笔交易,每笔交易都由 签名Si、公钥Pi 和 消息mi 组成 。现在我们只关心区块中所有的签名(而不是每一个)是否正确 。为获得聚合签名,只需要将区块中的所有签名加起来:
S=S1+S2+...+S1000
为了验证该区块是否正确 , 要保证下面这个等式成立 。
e ( G , S ) =  e ( P1 , H(m1) ) × e ( P2 , H(m2) ) × ... × e ( P1000 , H(m1000) )
如果签名是有效的 , 那么该等式是成立的 。证明如下:(这里我直接放word里的截图)
BLS签名算法

文章插图
这里我们仍需用到所有的公钥,并计算 1001 次配对函数 , 好处是,区块中的签名只占 33 字节了 。签名聚合可以由矿工在挖矿时完成,节省大量的区块空间 。
4.1 n-n多重签名使用多重签名的地址时,我们会对同一笔交易用不同的密钥进行签名 。这种情况下,可以和 Schnorr 算法一样使用聚合密钥,把所有密钥和签名聚合成单个公钥和签名 。
下面我们以 3-3 多重签名方案为例(同理可推导任意数量的多重签名方案) 。一种简单的聚合方法,是把所有的签名和密钥加起来即可 。即:
签名聚合结果:S=S1+S2+S3密钥聚合结果:P=P1+P2+P3   可以验证以下等式依然成立: e ( G , S ) =  e ( P , H(m) )   证明如下:(这里我直接放word里的截图)
BLS签名算法

文章插图
和 Schnorr 一样,我们也需要杜绝伪造密钥攻击 。一种方法是要求每个签名参与者证明它拥有公钥对应的私钥(用私钥给公钥签名) 。另一种方法是加入非线性系数 , 使得攻击无法实施 。要做到这一点,聚合不再是简单的将多个密钥和签名相加,而是将它们分别乘以某个系数后再相加:
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)
此时,上面的验证公式依然成立 。虽然多了系数ai,但计算逻辑未变 。
该方案的好处是,无需在设备间进行多轮通信,只需知晓其它签名者的相应信息即可 。它可比 Schnorr 算法(需要 3 轮通信)的多重签名方案简单多了 。这个方案也不依赖随机性,是一种具有完全确定性的签名算法 。
4.2 m-n多重签名上面对n-n多重签名进行了介绍,但实际中其实并不是很常见,更常用的是m-n多重签名 。
Schnorr 签名算法中 , 我们用公钥组成的默克尔树来实现密钥聚合,这种方式效率不高,但是将将堪用 。不幸地是 , 当 m 和 n 的值变大时,默克尔树的大小会呈指数增长 。

推荐阅读