Schnorr签名是比特币Taproot软分叉的一部分,Alice和Bob使用公钥抵消攻击,Alice和Bob各自选择一个大私有随机数,并生成挑战标量,最终生成一个聚合公钥和签名。Shamir秘密共享方案可以防止参与者了解有关秘密的任何信息,无脚本式门限签名方案可以让Alice、Bob和Carol每个人都收到可由任意两个人花费的资金。Bob告知Alice Carol无法联系,可以解决此攻击。
原文来源:Mastering Bitcoin, 3rd Edition
原文作者:Andreas M. Antonopoulos,David A. Harding
编译:Kurt Pan,XPTY
1989 年,Claus Schnorr 发表了一篇描述后来以他命名的签名算法的论文。该算法并不为比特币和许多其他应用所使用的椭圆曲线密码学(ECC) 所特有,尽管可能与椭圆曲线密码学关系是最密切的。 Schnorr 签名有许多良好的性质:
在本章后面,我们将完全按照比特币中使用的方式描述 Schnorr 签名算法,但我们将从它的简化版本开始,分阶段逐步实现实际协议。
Alice 首先选择一个大的随机数 (), 称为她的私钥。她还知道比特币椭圆曲线上的一个公共点, 称为生成元 () 。Alice 使用椭圆曲线乘法将 乘以她的私钥 , 这时 被称为标量, 因为它按比例缩放了 。得到的结果 , 称之为 Alice 的公钥。Alice将她的公钥发给Bob。尽管 Bob 也知道 , 但离散对数问题阻止了 Bob 把 除以 以导出 Alice 的私钥。
之后的某个时刻,Bob 希望 Alice 通过证明她知道 Bob 之前收到的公钥 () 对应的标量 来证明自己的身份。 Alice 不能直接给 Bob ,因为这会让Bob可以向其他人证明他是Alice,所以Alice需要在不向 Bob 透露 的情况下证明她知道 ,这称为零知识证明。下面我们开始介绍 Schnorr 身份识别过程:
通过使用简单整数而不是椭圆曲线上的点来替换前面提到的每个值(包括 )来构造一个不安全的过度简化版本,可能会更容易去理解交互式 Schnorr 身份识别协议。例如,我们将使用3 作为一开始的素数:
设置: Alice 选择 作为她的私钥。她将其乘以生成元 , 得到她的公钥 。她给Bob 发送 15 。
当然,这是一个过于简化的例子。当处理简单整数时,我们可以将乘积除以生成元 从而得到底层的标量,这是不安全的。这就是为什么比特币中使用的椭圆曲线密码学的一个关键性质就是做乘法很容易,但除以曲线上的点实际上是不可能的。此外,对于这么小的数字,通过穷举找到底层的值(或其他有效值)会很容易;比特币中使用的数要大得多。
讨论一下交互式 Schnorr 身份识别协议的一些使其安全的性质:
这里描述的交互式身份识别协议与 Claus Schnorr 的部分原始描述相匹配,但缺少去中心化比特币网络所需的两个必要性质。第一,依赖于Bob等待Alice承诺她的公共随机数,之后Bob再给她一个随机挑战标量。在比特币中,每笔交易的花费者都需要经过数千个比特币全节点的认证,包括尚未启动但其运行者有一天想要确保他们收到的比特币确实来自每个交易都有效的转账链的未来节点。今天或将来任何无法与 Alice 通信的比特币节点都将无法认证她的交易,且将与认证该交易的所有其他节点产生分歧。对于像比特币这样的共识系统来说,这是不可接受的。为了让比特币正常运作,我们需要一个不需要 Alice 和每个想要认证她身份的节点之间进行交互的协议。
一种简单的技术(以其发现者命名的 Fiat-Shamir 转换)可以将 Schnorr 交互式身份识别协议转变为非交互式数字签名方案。回想一下步骤 1 和 2 的重要性——包括按顺序执行它们的重要性。 Alice 必须承诺一个不可预测的随机数;Bob必须在收到Alice的承诺后才给她一个不可预测的挑战标量。再回想一下安全密码学哈希函数的性质:当给定相同的输入时,它将始终产生相同的输出,但当给定不同的输入时,它将产生与随机数据无法区分的值。
这就使得 Alice 可以选择她的私有随机数, 导出她的公共随机数, 然后对公共随机数进行哈希以获得挑战标量。因为 Alice 无法预测哈希函数的输出(挑战), 并且对于相同的输入 (随机数) 输出总是相同的, 所以这确保了Alice获得了一个随机挑战, 即使是她自己选择随机数并对其进行哈希运算的。我们不再需要来自Bob的交互。Alice只需发布她的公共随机数 和标量 , 数千个全节点(过去和未来的)中的每一个都可以对 进行哈希运算以生成 , 从而生成 , 然后验证 。明确写出来的话, 验证方程变为了 。
我们还需要一件事来完成将交互式 Schnorr 身份识别协议转换为对比特币有用的数字签名协议。我们不仅希望 Alice 证明她知道她的私钥;还想让她有能力对一个消息进行承诺。具体来说,我们希望她承诺与她想要发送的比特币交易相关的数据。有Fiat-Shamir 转换在这里,我们已经有了一个承诺,因此可以简单地让它额外去承诺消息。我们现在使用 也承诺消息 ,而不是 ,其中 ||代表串联。
我们现在已经定义出了 Schnorr 签名协议的一个版本,但我们还需要做一件事来解决一个比特币特定的问题。在 BIP32 密钥派生中,未强化派生的算法给定公钥并向其添加一个非秘密值以生成派生公钥。这意味着还可以将该非秘密值添加到用一个密钥的有效签名中,以生成用相关密钥的签名。该相关签名是有效的,但未经拥有私钥的人授权,这是一个重大的安全故障。为保护 BIP32 未强化的派生并支持人们想要在 Schnorr 签名之上构建的多种协议,比特币版本的 Schnorr 签名(称为 secp256k1上的BIP340 Schnorr 签名)除了对公共随机数和消息承诺之外还承诺所使用的公钥。这使得完整的承诺为。
现在我们已经描述了 BIP340 Schnorr 签名算法的每个部分并解释了它们的作用,我们可以定义协议了。整数相乘以模 进行,表示运算结果需要除以数字 (定义在secp256k1 标准中)并使用余数。数字 非常大,但如果它是 3 且运算结果是 5的话,那么我们实际使用的数字是 2(即 5 除以 3 余数为 2)。
设置: Alice 选择一个大随机数 () 作为她的私钥(直接选择或使用 BIP32 等协议从大的随机种子值确定性地生成私钥)。她使用 secp256k1 中定义的参数将生成元 乘以她的标量 , 生成 (她的公钥)。她将她的公钥提供给随后会认证她的比特币交易的每个人(例如, 通过将 包含在交易输出中)。当她准备好支出时, 她就开始生成她的签名:
一个Schnorr 签名由两个值组成: 和 。 值是比特币的椭圆曲线(称为 secp256k1)上的一个点,通常由两个 32 字节的坐标表示,(x, y)。但因为只需要 x 坐标即可,因此仅包含该值。当你在比特币的 Schnorr 签名中看到 时请注意,它只是该点的 x 坐标。
值 是一个标量(用于与其他数字相乘的数)。对于比特币的 secp256k1 曲线,其长度永远不会超过 32 字节。
虽然 和 有时可以是用少于 32 字节表示的值,但不太可能会比 32 字节小太多,因此它们会被序列化为两个 32 字节的值(小于 32 字节的值会有前导零)。按照先 然后 的顺序序列化,正好产生 64 个字节。
Taproot软分叉(也称为 v1 segwit)将 Schnorr 签名引入了比特币,并且是截至撰写本文时在比特币中使用它们的唯一方式。当与 taproot 密钥路径或脚本路径支出一起使用时,64 字节 Schnorr 签名被视为使用默认签名哈希 (sighash),即 SIGHASH_ALL 。如果使用替代的签名哈希,或者支出者想要浪费空间以显式指定 SIGHASH_ALL ,则会将一个指定签名哈希的附加字节附加到签名上,使签名为 65 字节。
正如我们将看到的,64 或 65 字节都比“ECDSA 签名序列化 (DER)”中会描述的用于 ECDSA 签名的序列化要高效得多。
在上述单签名 Schnorr 协议中,Alice 使用签名 来公开证明她知道她的私钥,本例中称为 。想象如果 Bob 也有一个私钥 (),他想与 Alice 一起证明他们知道 ,且无需向对方或其他任何人透露他们的私钥。我们再来过一遍 BIP340 Schnorr 签名协议。
警告:我们将要描述的简化协议并不安全,原因将很快解释。在描述被认为是安全的相关协议之前,我们仅使用它来展示 Schnorr 多签名的机制。
Alice 和 Bob 需要导出 的公钥, 即 。由于可以使用椭圆曲线运算将两个椭圆曲线点相加, 因此首先 Alice 导出 , Bob导出 。然后他们将其加在一起以创建 。点 就是他们的聚合公钥。为了创建签名, 他们开始运行简单的多签名协议如下:
Alice和Bob已经证明了他们知道自己的私钥的和,且没有任何一个人将自己的私钥透露给对方或其他任何人。该协议可以扩展到任意数量的参与者(例如,一百万个人可以证明他们知道他们的一百万个不同密钥的和)。
上述协议存在多个安全问题。最值得注意的是,一方在确定自己的公钥之前可能会了解其他方的公钥。例如, Alice 诚实地生成她的公钥 并与 Bob 共享。Bob 使用 生成他的公钥。当它们的两个密钥组合在一起时 ,正负 项相互抵消, 因此公钥仅代表 的私钥(即 Bob 的私钥)。现在, Bob可以产生有效的签名, 而无需Alice的任何帮助。这称为密钥抵消攻击。
有多种方法可以解决密钥取消攻击。最简单的方案是要求每个参与者在与所有其他参与者共享有关该密钥的任何内容之前先承诺自己的公钥部分。例如,Alice和Bob各自哈希他们的公钥并彼此共享他们的摘要。当他们都拥有对方的摘要时,他们可以共享密钥。他们分别检查对方的密钥哈希值是否符合先前提供的摘要,然后再正常继续执行协议。这可以防止其中任何一个参与者选择一个公钥来抵消其他参与者的密钥。然而,这种方案很容易无法正确实现,例如通过未强化的 BIP32 公钥派生来简单地使用它。此外,它还为参与者之间的通信增加了一个额外的步骤,这在许多情况下可能是不可接受的。已经提出了更复杂的方案来解决这些缺点。
除了密钥抵消攻击之外,还有许多针对随机数的攻击。回想一下,随机数的目的是防止任何人能够利用他们对签名验证方程中其他值的了解来求解确定你的私钥的值。为了有效地实现这一点,你必须在每次签署不同的消息时使用不同的随机数或更改其他签名参数。不同的随机数不得以任何方式相关。对于多签名,每个参与者都必须遵守这些规则,否则可能会危及其他参与者的安全。此外,还需要防止抵消和其他攻击。实现这些目标的不同协议会做出不同的权衡,因此没有一个多签名协议可以在所有情况下推荐。相反,我们给出 MuSig 协议系列中的三个:
对于大多数应用来说,MuSig2 是撰写本文时可用的最佳多签名协议。
无脚本式多签名协议仅适用于 -of- 签名。拥有作为聚合公钥一部分的部分公钥的每一个人,都必须为最终签名提供部分签名和部分随机数。但有时,参与者希望可以只让其中的一部分进行签名,例如 -of-,即门限 () 个的参与者可以用由 个参与者构造的密钥进行签名。这种类型的签名称为门限签名。
我们在“脚本式多签名”一节中也看到了脚本式门限签名。但正如无脚本式多签名与脚本式多签名相比可以节省空间并提高隐私性一样,无脚本式门限签名与脚本式门限签名相比也可以节省空间并提高隐私性。对于没有参与签名过程的任何人来说,一个无脚本式门限签名看起来就像由单签名用户或通过无脚本式多签名协议创建的任何其他签名一样。
已知有多种用于生成无脚本式门限签名的方法,最简单的一种就是对我们之前看到的创建无脚本式多签名的方法进行轻微修改。该协议还依赖于可验证秘密共享(其本身依赖于安全的秘密共享)。
基本的秘密共享可以通过简单的分割来实现。 Alice 有一个秘密的数,她将其分成三个等长的部分并与 Bob、Carol 和 Dan 共享。这三个人可以按照正确的顺序组合他们收到的部分数(称为份额)来重构出Alice的秘密数。一个更复杂的方案需要Alice向每个份额添加一些附加信息,称为校正码,可以让三人中的任意两人恢复该数字。该方案并不安全,因为每个份额都会让其持有者了解Alice的秘密的部分知识,使得参与者会比没有份额的非参与者更容易猜测Alice的秘密。
安全的秘密共享方案可以防止参与者了解有关秘密的任何信息,除非他们组合了达到最小门限数量的共享。例如,如果 Alice 希望 Bob、Carol 和 Dan 中的任意两人能够重构她的秘密,则她可以设置门限为 2。最著名的安全的秘密共享算法是 Shamir 秘密共享方案,通常缩写为 SSSS。这是以其发现者命名,Shamir也是我们在“Schnorr 签名”中看到的 Fiat-Shamir 转换的发现者之一。
在一些密码学协议中,例如我们正在研究的无脚本式门限签名方案,Bob、Carol 和 Dan 知道 Alice 正确遵循了她这边的协议是至关重要的。他们需要知道她创建的份额都来自同一个秘密,需要知道她确实使用了她声称的门限,并且需要知道她给每个人的份额是不同的。能够完成所有这些要求且仍然是一个安全的秘密共享方案的协议就是一个可验证秘密共享方案。
要了解多签名和可验证秘密共享是如何工作的,想象Alice、Bob 和 Carol 每个人都希望收到可由他们中的任意两个人花费的资金。他们按照“基于 Schnorr 的无脚本式多签名”中的描述进行协作,生成一个常规的多签名公钥来接受资金 (-of-)。接着,每个参与者从他们的私钥中导出两个秘密份额——给其他两个参与者各一个。这些份额可以让其中的任何两人重构出多签名的原始部分私钥。每个参与者将其秘密份额之一分发给其他两个参与者,从而每个参与者存储自己的部分私钥以及每个其他参与者的一份份额。随后,每个参与者都会验证他们收到的份额(和给其他参与者的份额比)的真实性和唯一性。
之后,当(比如)Alice和Bob想要在没有Carol参与的情况下生成无脚本式门限签名时,他们将自己拥有的两份份额交换给Carol。这使他们能够重构Carol的部分私钥。 Alice 和 Bob 也有自己的私钥,于是他们可以使用所有三个必要的密钥来创建无脚本多签名。
换句话说,刚刚描述的无脚本式门限签名方案与无脚本式多签名方案相同,只是门限值数量的参与者有能力重构出不能或不愿签名的任何其他参与者的部分私钥。
这确实指出了在考虑无脚本式门限签名协议时需要注意的一些事项:
尽管多个比特币贡献者已经对该主题进行了大量研究,但尚未有无脚本式门限签名协议作为 BIP提出,我们期望在本书出版后会出现经过同行评议的解决方案。