Schnorr 签名方案和 BLS 签名方案的全面对比

原文:https://medium.com/cryptoadvance/bls-signatures-better-than-schnorr-5a7fe30ea716https://medium.com/cryptoadvance/how-schnorr-signatures-may-improve-bitcoin-91655bcb4744
 

Schnorr 签名算法最初是由德国密码学家 Claus Schnorr 于 2008 年提出的,而来自区块链协议公司 Blockstream 的密码学家 GregoryMaxwell、PieterWuille 等人,则在 2018 年提出了一种名为 MuSig 的 Schnorr 签名方案,这也是我们即将探索的签名方案。而 BLS 签名方案,最初是由斯坦福大学教授 DanBoneh 等人于 2001 年便提出的一种方案,目前则在 Boneh 教授等人的完善下,变得更适用于区块链。总的来说,两大签名方案各有千秋,它们在不同的场景下都有各自的优势。以下内容译自量子物理学家 Stepan 的两篇科普文章(part1 和 part2),总结部分略有改动:

目录:

1、椭圆曲线数字签名算法(ECDSA)

2、什么是 Schnorr 签名?

3、Schnorr 签名的批量验证

4、Schnorr 签名的密钥聚合

5、MuSig:由 Blockstream 提出的 Schnorr 签名方案6、默克尔多重签名(Merkle Multisig)

7、什么是 BLS 签名方案?

8、BLS 签名的魔法

9、BLS 签名方案的具体原理10、BLS 签名的签名聚合

11、BLS 签名的密钥聚合和 n-of-n 多重签名

12、子群多重签名方案(m-of-n multisig)

13、BLS 签名可能的应用场景

14、BLS 签名的弊端:配对效率低下15、结论

Blockstream 曾在 2018 年初的时候发布了一份关于 MuSig 的论文,这是一种 Schnorr 签名方案,总的来说,这种签名方案的一些特征是非常好的,但其也存在着一些让人讨厌的其他特征。

1 椭圆曲线数字签名算法(ECDSA)

首先,我们需要明白,比特币目前使用的是 ECDSA 椭圆曲线数字签名算法,要对消息 m 进行签名,我们需对其进行哈希操作,并将此哈希视为一个数字:z = hash(m)。我们还需要一个随机或随机查找的数字 k。我们不喜欢信任随机数生成器(存在太多的故障,很多漏洞与糟糕的 RGN 有关),因此,我们通常会使用RFC6979,并根据我们的秘密和我们要签名的消息,计算确定性 K 值。

使用私钥 pk,我们可以为包含两个数字的消息 m 生成签名:r (随机点 R 的 x 坐标 = k×G) 和 s = (z+r⋅pk)/k。然后,使用我们的公钥 P = pk×G,任何人都可通过检查点 (z/s)×G+(r/s)×P 的 x 坐标等于 r,来验证我们的签名。

这个算法很常见,也很棒,但它也是可改进的。首先,签名验证包括反转(1/s)和两点乘法,这些操作的计算量非常大。在比特币中,每个节点都必须验证所有交易。这意味着当你广播一笔交易时,数千台计算机将不得不验证你的签名。而简化验证过程将是非常有益的,即使签名过程会更加困难。

第二,每个节点必须分别验证每个签名。如果是 m-of-n 多重签名交易节点,则可能需多次验证相同的签名。例如,具有 7-of-11 多重签名输入的交易将包含 7 个签名,并且需要对网络中的每个节点进行 7-11 次的签名验证。同样,这样的交易会占用大量的空间,你必须为此支付大量的费用。

2 什么是 Schnorr 签名

Schnorr 签名的生成则略有不同,我们使用了一个点 R 和一个标量 s 来代替两个标量(r,s)。与 ECDSA 相似的是,R 是椭圆曲线(R=K×G)上的一个随机点。签名的第二部分计算略有不同 :

     s = k + hash(P,R,m) ⋅ pk. 这里的 pk 是你的私钥,而 P = pk×G 则是你的公钥,m 是消息。然后可通过检查 s×G = R + hash(P,R,m)×P 来验证这个签名。

这个方程是线性的,所以方程可互相加减,并且仍然有效,这就给我们带来了几大关于 Schnorr 签名的好处。

3 Schnorr 签名的批量验证

要验证比特币区块链中的区块,我们需确保区块中的所有签名都有效。如果其中一个是无效的,我们不会在乎是哪个无效的,我们只会拒绝掉整个区块。

对于 ECDSA 签名算法,每个签名都必须单独验证。也就是说,如果区块中有 1000 个签名,我们就需要计算 1000 次倒置和 2000 次点乘运算,总共约 3000 次繁重的计算任务。

而通过使用 Schnorr 签名,我们可以将所有签名验证方程相加,从而节省一些计算能力。对于有 1000 个签名的区块而言,我们需验证:

(s1+s2+…+s1000)×G=(R1+…+R1000)+(hash(P1,R1,m1)×P1+hash(P2,R2,m2)×P2+…+hash(P1000,R1000,m1000)×P1000)

这里我们有一堆加法(在计算能力上几乎是免费的)以及 1001 次点乘法。我们需要为每个签名计算大约一次繁重的计算。

(图 4: 两个签名的批验证图,由于验证方程是线性的,只要所有签名都有效,几个方程的和就有效。我们节省了一些计算能力,因为标量和点加法比点乘法容易得多)

4 Schnorr 签名的密钥聚合

我们希望让自己的比特币保持安全,所以我们可能希望使用至少 2 个不同的私钥来控制我们的比特币。比如说一个放在笔记本电脑或手机,另一个则放在硬件钱包 / 冷钱包。因此,当其中一个受到威胁时,我们仍然可以控制我们的比特币。

目前,它是通过 2-of-2 多重签名脚本来实现的,这需要在交易中包含两个单独的签名。而使用 schnorr 签名,我们可以使用一对私钥(pk1,pk2),并生成一个与共享公钥 P=P1+P2=pk1×G+pk2×G 对应的共享签名。要生成这个签名,我们需要在每个设备上选择一个随机数(k1,k2),生成一个随机点 Ri=ki×G,将它们相加以计算一个公共哈希 (P,R1+R2,m),然后从每个设备 (si = ki + hash(P,R,m) ⋅ pki) 中获取 s1 和 s2。然后我们可以将这些签名相加,并使用一对 (R, s) = (R1+R2, s1+s2) 作为我们对共享公钥 p 的签名。其他所有人都无法说出它是否是聚合签名,它看起来与普通 schnorr 签名完全相同。

这种构造有 3 个问题,第一,从用户界面的角度来看,要进行交易,我们需要进行几轮通信,计算公共 R,然后-签名。有了两个私钥,只需一次访问冷钱包就可以完成:我们在在线钱包上准备一个未签名的交易,选择 k1,将 R1=K1×G 与未签名的交易一起记下。然后我们将这些数据传送到冷钱包并签名。因为我们已经有了 R1,所以我们可以一次性在冷钱包上签署交易。从冷钱包中,我们得到了 R2 和 s2,并将其传输回在线钱包。在线钱包使用之前选择的 (k1, R1) 签署交易,结合签名并广播签名交易。这与我们现在的情况非常相似,但一旦添加第三个私钥,一切就会变得更加复杂。比方说,你有一笔财富,它是由 10 个私钥控制的,它们存储在世界各地不同的安全位置,然后,你需要进行一笔交易。目前,你只需要浏览所有这些位置一次,但如果你使用的是密钥聚合,则需要执行两次,以组装所有 RI,然后签名。在这种情况下,最好在不进行聚合的情况下保留单独的签名,然后我们就需要 3 轮通信:

  1. 选择一个随机数 ki 和相应的 Ri=ki×G,然后只告诉每个人其哈希 ti=hash(Ri),这样每个人都可以确定在学习了其他随机数之后你不会改变主意;
  2. 把所有的数字汇总起来,计算出共同的 R;
  3. 签名;

第二个问题是已知的恶意密钥攻击。无论是在论文还是这篇文章中,都有很好的描述,所以我不想详细讨论。其想法是,如果你的某个设备被黑客攻击(比如说,你的在线钱包),并假装其公钥是 (p1-p2),那么它可以用它的私钥 pk1 控制共享资金。一个简单的解决方案是,在设置设备时,需要使用相应的私钥对公钥进行签名。

还有第三个重要问题。不能使用确定性 k 进行签名。有一种简单的攻击方式,如果你使用确定性 K,它允许黑客获得我们的私钥。攻击看起来会是这样的:有人入侵了我们的笔记本电脑,并完全控制了两个私钥中的一个(例如 pk1)。我们可能觉得是安全的,因为我们的比特币需要来自 pk1 和 pk2 的聚合签名。因此,我们尝试像往常一样进行交易,准备一个未签名的交易和 R1 值,将它们转移到我们的硬件钱包并在那里签名。然后返回 (r2,s2) 和……我们的在线钱包发生了一些事情,它无法签名和广播。我们再次尝试,但我们被黑的电脑这次使用了另一个随机值 R1'。我们再次与我们的硬件钱包签署相同的交易,并将值 (r2,s2) 带回我们被黑的电脑。然后,糟糕的事就发生了,我们的比特币就丢失了。

在这个攻击中,黑客为同一笔交易获得一对有效的签名:(R1, s1, R2, s2) 和 (R1', s1', R2, s2'),这里 R2 是相同的,但 R = R1+R2 和 R'=R1'+R2 是不同的,这意味着黑客可以计算我们的第二个私钥:s2-s2'=(hash(P,R1+R2,m)-hash(P,R1'+R2,m))⋅pk2 and pk2=(s2-s2')/(hash(P,R1+R2,m)-hash(P,R1'+R2,m))。我发现这是密钥聚合最不方便的特性:我们需要在任何地方使用好的随机数生成器来使用密钥聚合。

5 MuSig:由 Blockstream 提出的 Schnorr 签名方案

MuSig 方案解决了其中一个问题,它使得密钥盗窃攻击成为了不可能
。目标是将多个参与方 / 设备的签名和公钥聚合到一个参与方 / 设备,但不能证明你拥有与公钥对应的私钥。

聚合签名对应于聚合公钥。但是,我们不只是将所有联合签名者的公钥相加,而是将它们乘以某个因子。聚合的公钥将是 P=hash(L,P1)×P1+…+hash(L,Pn)×Pn。这里 L=hash(P1,…,Pn) 是一个取决于所有公钥的公用数字。这种非线性特性可以防止攻击者构造一个不好的公钥,例如在恶意密钥攻击当中。尽管攻击者知道自己的哈希 (L,Patk)×Patk 应是什么,但他不能从中派生 Patk,这和从公钥派生私钥是相同的问题。

剩余部分和前面的情况非常相似,为了生成签名,每个联合签名者选择一个随机数 ki,并与其他人共享 Ri=ki×G。然后将所有这些随机点相加到一个 R=R1+…+Rn,生成签名 si = ki + hash(P,R,m) ⋅ hash(L,Pi) ⋅ pki。这个聚合签名是 (R, s)=(R1+…+Rn, s1+…+sn),验证方程与之前相同:s×G = R + hash(P,R,m)×P。

6 默克尔多重签名(Merkle Multisig)

你可能会注意到,MuSig 和密钥聚合都需要所有签名者签署一笔交易。但是,如果你要的是一个 2-of-3 的多重签名呢?在这种情况下,是否可以使用签名聚合,或者我们必须使用我们通常使用的 OP_CHECKMULTISIG 和单独的签名?

嗯,这是可能的,但是协议有一个小的改变。我们可以开发一个类似 OP_CHECKMULTISIG 的新 op 码,它检查聚合签名是否与公钥的默克尔树中的特定项对应。

例如,如果我们使用带有公钥 p1、p2 和 p3 的 2-of-3 多重签名,那么我们需要为所有可使用的组合构造一个聚合公钥的默克尔树: (P1, P2), (P2, P3), (P1, P3),并将根放到锁定脚本中。为了使用比特币,我们提供了一个签名以及一个证明我们的公钥在默克尔树上的证据。对于 2-of-3 多重签名,默克尔树中只有三个元素,证明将由两个哈希组成,其中一个是我们想要使用的哈希,另一个则是其邻哈希。而对于 7-of-11 的多重签名,已经有 11!/7!/4!=330 种可能的密钥组合,而证明需要 8 个元素。一般来说,证明中的元素数量几乎与多重签名种的密钥数成线性关系 ( log2(n!/m!/(n-m)!)。

但是,有了公共密钥的默克尔树,我们不局限于 m-of-n 的多重签名。我们可以用任何我们想要的公共密钥制作一棵默克尔树。例如,如果我们有一台笔记本电脑、一部电话、一个硬件钱包和一个恢复种子,我们可以构建一个结构,允许我们将比特币与一台笔记本电脑、一个硬件钱包、一部电话和一个硬件钱包或仅与一个恢复种子一起使用。只有当你用分支和其他东西构造更复杂的脚本时,仅使用 OP_CHECKMULTISIG 会是不可能的。

                                    聚合公钥的默克尔树,不仅仅是 m-of-n 多重签名

7 什么是 BLS 签名方案

BLS 签名方案最初是由斯坦福大学教授 DanBoneh 等人于 2001 年就提出的一种签名方案(原论文地址:https://www.iacr.org/archive/asiacrypt2001/22480516.pdf),而在 2018 年,Boneh 教授还与 IBM 研究机构的 ManuDrijvers 等人更新了这种签名方案(https://eprint.iacr.org/2018/483.pdf)。

Schnorr 签名方案是非常了不起的,如果我们做得对,我们可以将交易中的所有签名和公钥组合为一个密钥和一个签名,没有人会发现它们对应于多个密钥。区块验证也可以变得更快,因为我们可一次性验证所有签名。但它也存在着一些问题:

  1. 多重签名方案需要多轮通信,这会使冷存储变得非常烦人;
  2. 对于签名聚合,我们必须依赖随机数生成器,我们不能像在 ECDSA 中那样确定地选择随机点 R;
  3. m-of-n 多重签名方案是棘手的,我们需要制作一个公共密钥的默克尔树(merkle tree),对于大数的 m 和 n 来说,这颗默克尔树可以变得相当大;
  4. 我们不能将区块中的所有签名组合为单个签名;

BLS 签名可修复上述所有问题,我们不需要随机数,区块中的所有签名都可以组合成单个签名,m-of-n 类型的多重签名非常简单,我们不需要签名者之间进行多轮通信。此外,BLS 签名相比 Schnorr 签名或 ECDSA 签名要小 2 倍,其签名不是一对,而是一个单曲线点。听起来似乎很棒,对吧,让我们看看它是如何工作的。

8 BLS 签名的魔法

在开始之前,我们需要两个新的结构:哈希到曲线(hashing to the curve)以及曲线配对(curves pairing)。

哈希到曲线(hashing to the curve)

通常对于 ECDSA 签名以及 Schnorr 签名,我们会哈希一则消息,并在签名算法中使用此哈希作为一个数字。而对于 BLS 签名,我们需要一个稍修改过的哈希算法,它直接哈希到椭圆曲线。最简单的方法是像往常一样哈希一则消息,并将结果视为点的 x 坐标。椭圆曲线(就像我们在比特币中使用的曲线)通常有 2²⁵⁶个点,而 SHA-256 哈希算法也给出了一个 256 位的结果。但是对于每个有效的 x 坐标,有两个点具有正和负的 y 坐标(因为如果(x,y)在曲线 y²=x³+ax+b 上,则(x,-y) 也在曲线上)。这意味着我们的哈希有大约 50% 的概率为一些 x 找到两个点,另有 50% 的概率无法找到。

      在有限域模 23 上定义的椭圆曲线 y²=x³+7 的玩具哈希例子。只有一半的 X 坐标有点,这里只有第三次尝试是成功的

要为任何消息找到一个点,我们可尝试哈希几次,方法是在消息中追加一个数字,并在失败时递增。如果 hash(m||0) 找不到点,我们尝试 hash(m||1)、hash(m||2) 等等,直到最后得到一个匹配的点。然后我们选择两个对应点中的一个,比如 y 较小的那个,然后我们就完成了。

曲线配对(curves pairing)

我们需要的另一件事是一个非常特殊的函数,它在一条曲线(或两条不同的曲线)上取两点 P 和 Q,并将它们映射至一个数字:

e(P, Q) → n.

我们还需要这个函数的一个重要属性。如果我们有一些秘密数字 x 和两点 P 和 Q,不管我们用哪个点乘以这个数字,我们都应得到相同的结果:

即:e(x×P, Q) = e(P, x×Q).

基本上,我们需要能够在不改变结果的情况下交换两个参数之间的点乘数。更普遍地说,所有这些互换都应产生相同的结果:

e(a×P, b×Q) = e(P, ab×Q) = e(ab×P, Q) = e(P, Q)^(ab)

我不想描述这个函数是如何精确工作的。基础数学相当复杂,如果你想知道所有令人讨厌的细节,我建议你阅读这篇文章和其中的参考资料。如果你想更深入一些,那这篇论文(https://crypto.stanford.edu/pbc/thesis.pdf)会比较适合你。目前,我们只需要接受这种函数的存在,它们不会泄露关于我们的秘密数字 X 的任何信息。

一个重要的注意项是,我们不能在这里使用任何椭圆曲线(特别是标准比特币曲线 secp256k1 不起作用)。为了使这个函数高效和安全,我们必须使用来自“友好配对”家族非常特殊的曲线。

9 BLS 签名方案的具体原理

现在我们有了构建 BLS 签名所需的一切。和往常一样,我们的私钥是一些秘密数字 pk,我们的公钥是 P = pk×G,我们要签名的消息则是 m

为了计算签名,我们将消息哈希到曲线 H(m) ,并将结果点乘以私钥 : S = pk×H(m). 就是这样了!没有别的东西,没有随机数,没有额外的操作,只有哈希乘以私钥!我们的签名只是曲线上的一个单点,在压缩序列化格式中只需要 33 个字节!

       BLS 签名生成,为了获得签名,我们将消息的哈希值乘以私钥

要验证此签名,可以使用我们的公钥 P 并检查:

e(P, H(m)) = e(G, S)

这为真,因为上面描述的配对函数的优良特性:

e(P, H(m)) = e(pk×G, H(m)) = e(G, pk×H(m)) = e(G, S)

BLS 签名验证 , 我们只需要检查公钥和消息哈希是否映射到与曲线生成器点和签名相同的数字

这个签名方案既美观又简单,此外也有几个非常好的功能,特别是对比特币而言。

10 BLS 签名的签名聚合

现在,让我们组合区块中的所有签名!假设我们有一个包含 1000 笔交易的区块,每笔交易都包含一个签名 Si、一个公钥 Pi 以及一个签名为 mi 的消息。如果我们可以合并所有签名,为什么要存储所有的签名?毕竟,我们只关心区块中的所有签名是否有效。聚合签名将只是区块中所有签名的总和:

S = S1+S2+…+S1000

要验证区块,我们需要检查以下等式是否成立:

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))

我们仍然需要知道所有的公钥并计算 1001 个配对函数,但是至少区块中的所有签名只占用 33 个字节。签名聚合可以由矿工完成,并节省区块大量的空间。

11 BLS 签名的密钥聚合和 n-of-n 多重签名

如果我们使用多重签名地址,我们将使用不同的密钥签署相同的交易。在这种情况下,我们可以像在 Schnorr 签名方案中那样进行密钥聚合,在 Schnorr 中,我们将所有签名和所有密钥组合到一对密钥和一个签名上。以常见的 3-of-3 多重签名方案为例(对于任何数量的签名者都可以这样做)。

组合它们的一个简单方法,是将所有签名和所有密钥添加到一起。结果将是签名 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))

和 Schnorr 签名方案一样,运用 BLS 签名需要保护自己免受流氓密钥攻击。我们可通过要求每个联合签名者证明他们具有的公钥的私钥(通过签名他们的公钥),或者我们可以在方案中添加一些非线性元素,使恶意密钥攻击成为不可能。我们不是简单地将所有的密钥和签名相加,而是将它们乘以一个特定的数字,然后再相加:

S = a1×S1+a2×S2+a3×S3P = a1×P1+a2×P2+a3×P3

在这里,签名和密钥的系数是根据签名者的公钥和所有其他公钥来确定计算的:

ai = hash(Pi, {P1,P2,P3})

例如,它可以只是签名者公钥和用于签名的整个公钥集的级联:

ai = hash(Pi||P1||P2||P3).

同样的验证方程仍然有效。在证明中会有额外的系数 ai,但逻辑仍然存在。这个方案的好处在于,你不需要在设备之间进行多轮通信。你只需要知道谁是其他签名者。这比 Schnorr 签名的 3 轮多重签名方案要简单得多。它也不依赖任何随机性,它是一种完全确定的签名算法。

12 子群多重签名方案(m-of-n multisig)

通常,我们不会想用 n-of-n 的多重签名方案,我们更喜欢使用 m-of-n (比如说 2-of-3)的多重签名方案。我们不想因为丢了一把私钥就把钱给弄丢。在这种情况下,最好使用密钥聚合。有了 Schnorr 签名方案,我们就可以通过使用公共密钥的默克尔树来做到这一点,它不是最有效的办法,但很管用,坏处在于一旦 m 和 n 值很大,默克尔树(merkletree)的大小就会成倍放大。

而对于 BLS 签名方案,还有另一种方法。不过也没那么简单,我们需要一个普通的哈希函数,它输出一个数字 hash(x), 以及一个到曲线的哈希H(x)。当我们决定使用多重签名时,我们还需要一个“设置”阶段,但在此之后,我们不再需要通信,我们只需要签名来签署任何数量的交易。

再次,我将使用一个简单的例子,我们希望构建三个不同设备上存储密钥的 2-of-3 多重签名方案,但它可以扩展到任何值的 m 和 n。

设置阶段

我们的每个设备都有一个签名者编号 i=1,2,3,代表其在集合中的位置,一个私钥 pki 以及一个对应的公钥 Pi = pki×G。这里计算聚合公钥的方式与之前完全相同:

P = a1×P1+a2×P2+a3×P3,

ai = hash(Pi, {P1,P2,P3})

现在,每个设备都需要签名,而编号 i 是我们的聚合公钥的成员(对于每个 i),聚合这些签名并将结果保存到相应的设备上:MKi = (a1⋅pk1)×H(P, i)+(a2⋅pk2)×H(P, i)+(a3⋅pk3)×H(P, i)

这个签名我们称为“成员密钥”,稍后我们将使用它进行签名。每个成员密钥都是消息 H(P,i) 的有效 n-of-n 签名,这意味着:

e(G, MKi)=e(P, H(P,i))

记住这个方程,我们以后会用到的。它将用来证明我们是多重签名方案的有效参与者。

签名

现在假设我们只想用密钥 pk1 和 pk3 签署一笔交易。我们生成两个签名 S1 和 S3:

S1 = pk1×H(P, m)+MK1, S3=pk3×H(P, m)+MK3

并将它们相加以获得单个签名和密钥:

(S’, P’) = (S1+S3, P1+P3)

我在这里写为 P’ 和 S’,来强调这个密钥和签名只由签名者的一个子集签名,它与 P 不同,P 是所有签名者的聚合密钥。要验证这 3 个签名中的 2 个,我们需要检查:

e(G, S’) = e(P’, H(P, m))⋅e(P, H(P, 1)+H(P, 3))

我们记得成员密钥 MK1 和 MK3 是由聚合密钥 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))

就是这样,要比 n-of-n 复杂一点,但仍然是可被理解的。

13、BLS 签名可能的应用场景

要实现这个多重签名方案,我们需要将资金发送到与聚合公钥 P 对应的地址,并表示我们至少需两个签名。在比特币脚本语言中,锁定脚本可能如下所示:

OP_2OP_CHECK_BLS_MULTISIG

这里,OP_2 告诉我们需要两个密钥来签署消息。我们不会说任何地方总共就只有 3 个签名者,所以不能说它是 2-of-3 还是 2-of-100 多重签名地址。为了使用这个输出,我们需要在我们的案例 1 和 3 中提供参与签名者的密钥 P’、签名 S’ 以及索引。解锁脚本可能如下所示:

OP_1 OP_3

结合这些脚本,可以给我们提供所有必要的信息。从 OP_1 和 OP_3,我们知道我们需要计算哈希 H(P, 1) 和 H(P, 3),然后我们就拥有了验证交易所需的一切。这意味着对于任何 m 和 n,我们只需要:锁定脚本中的一个聚合公钥 P;参与签名者的一个聚合公钥 P’一个聚合签名;带有签名者索引的 m 数字;它非常紧凑,也很美!但它也并非完美…通常我们只使用一次地址(我们使用像 bip32 这样的密钥派生来生成新的私钥和地址),但是对于每一组新的私钥,我们也需要一组新的成员密钥。一种不用每次都运行设置阶段的方法是生成一组密钥,比如 1000 个密钥,并获得相应的成员密钥。毕竟,它们只有 32 字节大小,然后,只有在使用了所有 1000 个地址时,我们才需要再次运行设置阶段。

14 BLS 签名的弊端:

配对效率低下正如本文以及很多技术大佬在 Twitter 上所指出的,上面的讨论没有谈到一个重要的部分,而它可能是 BLS 签名方案最大的缺陷。BLS 签名的配对是很难的,我们认为神奇的函数 e(P, Q) 是有效和安全的,但事实并非如此。BLS 签名验证要比 ECDSA 签名验证的难度大上几个数量级。对于具有 1000 笔交易的整个区块的签名聚合,仍然需要计算 1000 次配对,因此验证一个区块中的一个小签名,可能比验证 1000 个单独的 ECDSA 签名需要更长的时间。这里 BLS 签名能够实现的唯一好处,在于我们可以在区块中容纳更多的交易,因为聚合签名只需要大约 32 个字节。与 BLS 签名不同,Schnorr 签名是非常有效的,它们可以一起验证,而且这个过程比 ECDSA 效率高 3 倍。另外,配对函数是复杂的,如果我们不够小心,它会成为我们的敌人。一方面,我们希望配对能够有效地、更快地验证签名,另一方面,我们不希望透露任何关于我们密钥的信息。这两大需求相互竞争,我们需要非常小心地选择对配对友好的曲线。实际上有一种针对椭圆曲线加密系统的攻击方法称为 MOV 攻击(以 Menezes,Okamoto 和 Vanstone 命名),它允许使用我们的魔法配对函数来降低系统的安全性。所以我们真的需要小心。然后问题就出现了:什么对我们而言会更重要?

15 结论

Schnorr 签名和 BLS 签名方案都有自己的独特之处,前者的主要缺点在于需要额外的通信回合,以及不适合较大值 m 和 n 的多重签名方案,后者的验证时间则是最大的弊端,两者共同存在的好处都是可聚合签名,节省区块空间。就目前来看,Schnorr 签名应用于比特币的可能性会更大,当然,方案都是可完善的,最终哪种协议能够被采用,依然是一个未知数。

原文地址:https://www.cnblogs.com/hzcya1995/p/13313646.html