当我们研究比特币 ECDSA 椭圆曲线签名算法时,就会发现多重签名交易验证过程非常繁琐,有没有设想过把一笔交易中的所有签名和公钥通通合并成单个签名和公钥,无法追溯并且简单快速?
*图片来源自网络
20世纪80年代,德国密码学家 Claus-Peter Schnorr 给出了答案。以他命名的 Schnorr 签名算法可以构建更高效和隐私性更强的区块链系统,一直备受区块链开发者们的关注。 2018 年 7 月,比特币开发者 Pieter Wuille 撰写了 bip-schnorr[2] 提出了将 bitcoin 的签名算法更改为 schnorr 方案。Schnorr 与 ECDSA 虽然同为使用 secp236k1[3] 曲线的椭圆曲线加密算法,但相比 Schnorr 来说,ECDSA 有一些不足之处:
证明安全性:在随机预言模型中很容易证明 Schnorr 签名的安全性,而 ECDSA 不存在这样的证明。
不可延展性:ECDSA 签名具有可塑性,不知晓私钥的第三方可以将给定公钥和消息的现有有效签名更改为对同一私钥和消息的另一个有效签名,这一问题直到 SegWit 激活后才得以修复。BIP62[4] 和 BIP66[5] 中讨论了此问题。而如果使用 Schnorr 签名则可以避免类似的情况出现[6]。
线性:Schnorr 签名是线性的,这一点非常重要。使用 Schnorr 签名的各方可以生成对其各自密钥的签名聚合。以这一特性作为基础,可以构建更高效和隐私性更强的区块链系统。
schnorr 签名算法相比 ECDSA 来讲,对于上述的优点,除了尚未标准化之外几乎没有缺点。而且由于两种算法都基于同一个椭圆曲线,整个关于签名的升级成本也是很低的。
什么是 Schnorr 签名?
在密码学中,Schnorr 签名是由 Schnorr 签名算法产生的数字签名。它是一种数字签名方案,以其简单高效著称,其安全性基于某些离散对数问题的难处理性。[7] Schnorr 的原理描述如下:
下面用小写字母表示数字,比如:a = 42。同时我们将使用一些椭圆曲线(elliptic curve)上的点。这些点是一些满足椭圆曲线方程的大数对。我们将用大写字母来表示这些点,比如:A = (4, 68)。椭圆曲线上的点可进行一些代数运算。其上两个点可以相加可以得到近似随机的第三个点,表示为:C = A + B。某个点可以与自身相加多次:D = C + C + C。当我们讲一个点与自身相加多次时,我们称其为“乘以一个数”:D = 3 * C。显而易见的,如果将一个点 A 与自身相加很多次(或者说将其乘以一个很大的数)然后得到一个点 B ,如果我们只是知道原始点 A 和结果点 B ,计算出与 A 相乘的这个大数是相当困难的。这里的“困难”意思是,如果要计算出这个“大数”,我们不能简单的用 B 除以 A ,只能不断的猜测一个值 x ,计算是否 x * A等于 B 。所以如果这个 x 的值非常大,甚至大于宇宙中所有原子数目的和,猜测这个 x 的值将花费一个难以接受的时间。同时如果某人持有正确的 x ,计算 x * A 是非常迅速的。这种非对称性将作为我们讨论的前提。
Alice 持有私钥 x ,然后选择一个随机数 r ,以及椭圆曲线上的原点 G ,计算出R := r * G,公钥X := x * G,使用哈希函数获取一个随机的用于验证的数字e := Hash(R, X, message),然后计算 s := e * x + r。
Alice 给 Bob 发送点 R, X, message ,和点数值 s ,Bob 验证 s * G 等于 R + e * X 。事实上,不仅是 Bob,这个世界上的任何人都可以独自对这一证明进行验证。一旦s * G = R + e * X通过了验证,既可以证明 Alice 持有私钥 x,并生成了一个合法的签名:(s, e)。
最终,如果要将签名从这一证明中创造出来,Alice 需要定制一个哈希函数来对她签名的消息的进行哈希计算。这样的话需要确定针对一个消息所计算出的签名,不能被复用给另外一个消息。
这个定制过程可以简单的通过将 R , X 和签名信息进行哈希来做到:
e := Hash(R, X, Message)
一个良好的哈希函数,会在哪怕仅有一个字符有更改的情况下,也会返回完全不同的哈希值,使得计算出 s 的值是不可能的任务
Schnorr 签名协议的简洁描述如下:
Setup:
x := random number (aka private key)
G := common point
X := x * G (aka public key)
Sign:
r := random number (aka nonce)
R := r * G (aka commitment)
e := Hash(R, X, message)(aka challenge)
s := r + e * x (aka response)
return (R, X, s, message) ((s, e) aka signature)
Verify:
receive (R, X, s, message)
e := Hash(R, X, message)
S1 := R + e * X
S2 := s * G
return OK if S1 qeuals S2
基于此,开发者在未来可以添加更复杂的概念,比如聚合签名。聚合签名优势就在于将一笔交易中所有涉及的输入只需要一个合并签名就可以完成,大大减少了数据处理量,使网络速度更快,更加高效。
什么是聚合签名?
聚合签名是使用 Schnorr 签名的各方生成的对各自密钥的签名聚合,它可以把一笔多签交易的各个参与方的公钥和签名合并为一个公钥与签名,整个合并过程是不可见的,无法从合并后的公钥与签名推导出合并前的信息,并且在验证时仅需一次验证即可。目前 ,Mimblewimble 已利用 Schnorr 签名算法实现签名聚合。
在使用 ECDSA 进行多签的情况下,如果共有 N 个私钥进行了签名,则验证时需要对 N 个签名各自进行验证。由于 Schnorr 签名算法的线形特性,在同样的情况下,N 个私钥的签名可以「聚合」成为一个签名,原理如下:
由于椭圆曲线上的点可以满足乘法结合律,因此对于椭圆曲线上的两个点 X,Y 和相应的标量(私钥)x,y 以及原点 G,则:
X + Y = x * G + y * G = (x + y) * G
对于 ECDSA 签名算法,验证 n 个签名,需要进行 n 次取模和 2 * n 次点乘运算。而对于 Schnorr 签名,我们可以将验证方程相加:
S1 = sum(s)(i) = s1 * G + s2 * G + ... + sn * G = (s1 + s2 + ... + sn) * G
S2 = sum(R + e*X)(i) = (R1 + e1 * X1) + (R2 + e2 * X2) + ... + (Rn + en * Xn) = sum(R1, R2, ..., Rn) + (e1 * X1 + e2 * X2 + ... + en * Xn)
此时对 Schnorr 签名算法生成的多签进行验证时,只需要进行 2n 次加法运算和 n + 1 次点乘运算即可。由于加法运算所占用的资源是极低的,两种多签验证方式的资源消耗可以近似的比较为:ECDSA 为一次取模加两次点乘,Schnorr 为一次点乘的资源消耗。显而易见的结论是,使用 Schnorr 签名算法所消耗的资源更少。
对于上述多重签名的情况,使用 Schnorr 签名算法进行聚合签名,可以提供如下额外的好处:
性能方面:可以大大减少验证签名的成本。Schonrr 签名算法的优势是显而易见的,对于一笔多签交易,原本需要进行多次的验证,而聚合签名仅需验证一次,从而提升节点对于交易的验证速度
交易体积:由于将多个签名聚合为一个签名,可以大大减少多重签名的大小,并且可以显著降低对于网络传输消耗的带宽,以及对于节点存储空间的占用
隐私:使用 Schnorr 聚合签名可以提高链上数据的隐私性。对于验证者来讲,聚合签名看起来和普通的 Schnorr 签名并无区别,无法分辨这一笔交易是普通的交易还是一笔多签交易,而参与交易的用户的公钥和签名都不会暴露出来
在创建一个基于 Schnorr 聚合签名的多签方案时,为保证多签的签名看起来像单密钥签名,并且使传统的验证方法有效并且保证整个过程只需要线性次签名聚合,该方案需要满足如下的特性:
在普通的公钥模型中被证明是安全的
满足 Schnorr 方程,从而可以将得到的签名写成公钥组合的函数
允许签名者需要合作的交互式聚合签名(IAS)
允许非交互式聚合签名(NAS),其中聚合可以由任何人完成
允许每个签名者签署相同的消息
允许每个签名者签署自己的消息
基于 Schnorr 的聚合签名方案目前有多种实现,最终 Blockstream 给出的方案是 MuSig,各个实现方式的区别以及 MuSig 的具体原理可以参照引用[8][9]。
聚合签名的使用
7月10日,Qtum量子链基金会宣布实现QTUM-BEAM原子交换(Atomic Swap),原子交换(Atomic Swap)允许两个独立链上进行原子性的跨链交易。(链接:Qtum量子链实现QTUM-BEAM原子交换,支持隐私跨链交易|附实验步骤详解)
而通过聚合签名,可以安全又简单的实现原子交换。聚合签名本质是一个签名的偏移量,一旦与真实的签名进行组合,即可计算出签名所用的私钥。聚合签名的可信度可以进行验证,同时又无需暴露任何信息。聚合签名可以保证原子交换的原子性,又可以保证交易双方的安全。
通过聚合签名进行一笔原子交换的简洁过程如下[10]:
Alice 和 Bob 将加密货币分别存入两个各自签名的地址之中
Alice 所用的私钥会是一次性的,因为她需要将这个私钥发送给 Bob
Alice 向 Bob 提供一个聚合签名,这个签名需要经过 Bob 的确认
当 Alice 广播她的签名来证明她持有的加密货币时,Bob 可以获得足够的信息计算出 Alice 的私钥并获得她持有的加密货币
Bob 签署一笔交易发送加密货币给 Alice
Alice 使用另一半私钥对接收加密货币的交易进行签名并将其广播
Bob 获知全部的私钥并收到 Alice 持有的加密货币,同时 Alice 也将获得 Bob 的货币
引入 Schnorr 和聚合签名的影响
优势:
节省数据:签名聚合可在区块链上提供数据压缩
隐私:除交易结算外,关于无脚本智能合约的任何东西都不会记录在区块链上(签名聚合过程发生在链下)
多重性:可在单个交易结算中在双方之间转移多种资产(跨链原子交换)
隐式可伸缩性:区块链的可伸缩性是通过将多个交易压缩到单个结算事务中实现的。只有满足所有先决条件后,交易才会被广播
结合聚合签名的 Scriptless script 相比标准智能合约具有更好的扩展性。因其合约执行是发生在链下的,通过将此执行结果推送给关心它的人,公共计算资源可以减轻存储合约数据和执行条件的负担。非公开的合约也可以提供更好的隐私性。合约的详情只有参与者可以知晓,对于其他人来说,该笔交易与普通的交易并没有什么区别
劣势:
Maxwell 等人的工作指出[11],满足密钥聚合的 Schnorr 多重签名的简单实现并不是安全的。在普通的公钥模型中,如使用 BN Schnorr 的签名方案,需要通过放弃密钥聚合的属性来获得安全性。他们提出了一个新的基于 Schnorr 的多签模型,叫做 MuSig,以在普通的公钥模型中可使用密钥聚合,并具备应有的安全性。其与标准的 Schnorr 签名具有相同的密钥和签名大小。对于单个「聚合」公钥可以通过与标准 Schnorr 签名相同的方式进行验证(通过签名者各自的公钥进行计算得出证明)。
引用
https://en.wikipedia.org/wiki/EllipticCurveDigitalSignatureAlgorithm
https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki
http://www.secg.org/sec2-v2.pdf
https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki
https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
提交公钥的限制是其取消了公钥恢复或根据短公钥哈希验证签名的能力。这些结构通常与批量验证不兼容。
https://en.wikipedia.org/wiki/Schnorr_signature
https://blockstream.com/2018/01/23/musig-key-aggregation-schnorr-signatures.html
https://eprint.iacr.org/2018/068.pdf
https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2017-03-mit-bitcoin-expo/slides.pdf
https://eprint.iacr.org/2018/068.pdf