密码学 | 多重签名:基于 Schnorr 的 MuSig 方案

⚠️原文:Schnorr Applications: MuSig

⚠️写在前面:本文属搬运博客,自己留存学习。



1 什么是多签名?

多签名 是指:一组签名密钥 ( X 1 , X 2 , . . . , X n ) (X_1, X_2, ..., X_n) (X1,X2,...,Xn) 共同生成一条消息的签名。

任何正常签名方案 —— 如 Schnorr 或 ECDSA —— 的多签名方案,最简单的方法是将每个签名者对给定消息的单个签名连接起来: s = ( s 1 , s 2 , . . . , s n ) s=(s_1, s_2, ..., s_n) s=(s1,s2,...,sn)

个人理解:默认的 Schnorr 或 ECDSA 是单签名方案,但它们也可以有多签名版本。最简单的方式,就是将各个单签名连接起来,构成一个多签名。

这个方案已在比特币中通过操作 OP_CHECKMULTISIG —— 简称 OP_CMS —— 得到支持。实际上,OP_CMS 支持更多的操作,你可以创建一个由 m-of-n 参与者控制的地址,其中 m ≤ n,但我们今天只考虑 n-of-n 的情况。

什么是 m-of-n 参与者?答:意思是,至少需要 n 个参与者中的 m 个人同意,才能生成一个有效的签名。当 m=1 时,它等同于传统的单签名方案,即只需要一个人同意即可生成签名。

虽然 OP_CMS 是一个正确的多签名方案,但它有一些严重的缺点。在这种方案中,n-of-n 多签名将是常规签名的 n 倍 大小,因为它需要在链上放置 n 个签名和公钥对。同样,这比验证单个签名需要更长的时间。最后,它没有隐私功能,因为所有参与者都是公开的,即所有 n 个密钥都必须用于验证。

为什么需要在链上放置 n 个签名和公钥对?答:因为在验证签名的时候,我们需要使用相应的签名和公钥。由于在 OP_CMS 方案中,一个多签名是由 n 个签名拼接来的,因此我们在验证时需要这 n 个签名和它们各自对应的公钥。

MuSig 旨在解决这些问题,它是一个 Schnorr 多签名方案。无论签字方的数量多少,它都能产生一个与普通 Schnorr 签名无法区分的签名。因此,MuSig 签名的验证与普通 Schnorr 签名完全相同。此外,它支持 密钥聚合,因此单个签名密钥可以保持私密。

与 OP_CMS 相比,MuSig 降低了存储负担、减少了验证时间、保护了密钥隐私😇

具体来说,假设有 n 个签名者 X 1 , X 2 , . . . , X n X_1, X_2, ..., X_n X1,X2,...,Xn 和一条消息 m m m,他们希望共同签署这条消息。通过使用 MuSig,他们可以生成一个单一的 Schnorr 签名 ( R , s ) (R, s) (R,s)

这将使用 聚合密钥 X = a g g ( X 1 , X 2 , . . . , X n ) X = agg(X_1, X_2, ..., X_n) X=agg(X1,X2,...,Xn) m m m 进行有效签名,这样在任何公共空间 —— 如区块链 —— 中,这 n 个签名者们可以假装自己只是一位拥有密钥 X X X 的签名者。简而言之,我们可以使得多签名输出和标准输出没有区别。



2 朴素 Schnorr 多签名

针对签名者 i i i,我们对其所使用的变量进行说明:

  • 私钥: x i x_i xi
  • 公钥: X i = x i ∗ G X_i=x_i*G Xi=xiG
  • 一次性私钥: k i k_i ki
  • 部分签名: R i = k i ∗ G R_i=k_i*G Ri=kiG
  • 部分签名: s i = k i + H ( X , R , m ) ∗ x i s_i=k_i+H(X, R, m)*x_i si=ki+H(X,R,m)xi

为什么叫作一次性私钥?答:签名者 i i i 每次签名都会重新生成一个随机值 k i k_i ki,对 k i k_i ki 是用完即弃,与 x i x_i xi 这种长期性私钥应该区分开来。

假设有 n n n 个签名者。

朴素 Schnorr 多签名让每个签名者分享自己的公钥 X i X_i Xi,计算并定义聚合密钥为:

X = X 1 + X 2 + . . . + X n X = X_1 + X_2 + ... + X_n X=X1+X2+...+Xn

让每个签名者生成并分享自己的部分签名 R i R_i Ri,计算并定义部分聚合签名为:

R = R 1 + R 2 + . . . + R n R = R_1 + R_2 + ... + R_n R=R1+R2+...+Rn

为什么 R i R_i Ri 被称为 部分签名 R R R 被称为 部分聚合签名?答:因为一个完整的签名是 ( R , s ) (R, s) (R,s),所以单独的 R R R s s s 只能算作部分签名或者部分聚合签名。

获得部分聚合签名 R R R 后,每个签名者可以自行计算他们的部分签名 s i s_i si

s i = k i + H ( X , R , m ) ∗ x i s_i = k_i + H(X, R, m)*x_i si=ki+H(X,R,m)xi

为了让 s i s_i si 们可以相加,朴素 Schnorr 多签名Schnorr 签名 中的 H ( X , R i , m ) H(X, R_i, m) H(X,Ri,m) 改为了 H ( X , R , m ) H(X, R, m) H(X,R,m)

然后再分享自己的部分签名 s i s_i si,计算并定义部分聚合签名为:

s = s 1 + s 2 + . . . + s n = ( k 1 + . . . + k n ) + H ( X , R , m ) ∗ ( x 1 + . . . + x n ) = k + H ( X , R , m ) ∗ x \begin{alignat}{2} s &= s_1 + s_2 + ... + s_n \\ &= (k_1 + ... + k_n) + H(X, R, m)*(x_1 + ... + x_n) \\ &= k + H(X, R, m)*x \end{alignat} s=s1+s2+...+sn=(k1+...+kn)+H(X,R,m)(x1+...+xn)=k+H(X,R,m)x

最终的朴素 Schnorr 多签名为 ( R , s ) (R,s) (R,s),涉及以下变量:

  • 聚合私钥: x x x
  • 聚合公钥: X X X
  • 聚合一次性私钥: k k k
  • 聚合部分签名: R R R
  • 聚合部分签名: s s s

验证者的验证等式为:

s ∗ G = ? R + H ( R , M ) ∗ X s*G\overset{?}{=} R+H(R,M)*X sG=?R+H(R,M)X

可以看出,上述方案不仅是一个 多签名方案,还是一个 聚合签名方案,因为它允许将多个签名合并为一个签名,隐藏掉了原始的单个签名的信息。遗憾的是,该方案容易受到所谓的 恶意密钥攻击 或称 流氓密钥攻击

英文是 Rogue Key Attack



3 恶意密钥攻击

假设我的公钥是 X 1 X_1 X1

我可以撒谎,将一个 X 1 ′ = X 1 − X 2 − . . . − X n X_1'=X_1 - X_2 - ... - X_n X1=X1X2...Xn 值传给其他签名者,并声称这就是我的公钥。这将导致聚合公钥 X X X 变为 X = X 1 ′ + X 2 + . . . + X n = X 1 X = X_1' + X_2 + ... + X_n = X_1 X=X1+X2+...+Xn=X1。又因为我是公钥 X 1 X_1 X1 的所有者,所以我知道 X 1 X_1 X1 对应的私钥。由此一来,我可以单方面将资金发送到任何我想要的地方,而无需任何合作。

首先,因为公钥都是公开的,所以我可以获取到所有其他签名者的公钥。接着,我令虚假公钥的值为 X 1 − X 2 − . . . − X n X_1 - X_2 - ... - X_n X1X2...Xn,以此使聚合公钥 X X X 退化为我的公钥 X 1 X_1 X1 。最后,我便可以为所欲为😈

如果你要求我证明:我对声称属于我的公钥拥有私钥,这将阻止我的恶意密钥攻击,但我还可以对随机数值 R i R_i Ri 执行相同的攻击,以控制聚合一次性私钥 k k k

原文中的 nonce 值是什么意思?答:nonce 是 number once 的缩写,在密码学中 nonce 是一个只被使用一次的任意或非重复的随机数值。

然后,我会在接收完所有其他签名者的部分签名 s i s_i si 之后,计算出聚合签名 s = k + H ( X , R , m ) ∗ x s = k + H(X, R, m)*x s=k+H(X,R,m)x,这将允许我计算出 x x x,再次让我能够不合作地将所有资金发送到任何地方。

刚才已经获取到了 k k k 值, s s s H ( X , R , m ) H(X, R, m) H(X,R,m) 又是已知的,因此可以倒推出 x x x 的值。



4 改进方案

为了修复上述方案,我们需要确保聚合随机数值 R R R 和聚合公钥 X X X 能够抵御恶意密钥攻击。

具体来说,我们要求每个签名者广播自己的随机数 R i R_i Ri 的哈希值 t i = H ( R i ) t_i = H(R_i) ti=H(Ri) —— 而非 R i R_i Ri 本身 —— 并且只有在看到所有其他签名者的 t i t_i ti 之后才揭示自己的随机数 R i R_i Ri

这里说的其实就是一个哈希承诺的过程,请自行补课密码学承诺😇

这种方案能够缓解对随机数 R i R_i Ri 的攻击,但对聚合签名公钥 X X X 来说却不切实际。因为公钥通常是公开的并且可以被重复使用。

上述方案相当于是把 R i R_i Ri 藏起来,但 X i X_i Xi 作为公钥是需要被公开的,因此不切实际。

因此,我们可以尝试改变我们的聚合公钥 X X X,使其通过所有签名公钥 X i X_i Xi 的哈希值来计算。

具体来说,令 L L L 为所有公钥的集合 ( X 1 , X 2 , . . . , X n ) (X_1, X_2, ..., X_n) (X1,X2,...,Xn) 的某种编码,然后让:

a i = H ( L ∣ ∣ X i ) a_i = H(L||X_i) ai=H(L∣∣Xi) X = a 1 ∗ X 1 + a 2 ∗ X 2 + . . . + a n ∗ X n X = a_1*X_1 + a_2*X_2 + ... + a_n*X_n X=a1X1+a2X2+...+anXn

其中 H H H 表示哈希函数。

终于看到论文中使用的方法了,喜极而泣😈

这样就很难从 ( X 1 , X 2 , . . . , X n ) (X_1, X_2, ..., X_n) (X1,X2,...,Xn) 中计算出一个 X 1 ′ X_1' X1 使得 X = X 1 X = X_1 X=X1 了。

然而,这样的修改会使聚合私钥 x = x 1 + . . . + x n x=x_1 + ... + x_n x=x1+...+xn 的值不再是聚合公钥 X X X 对应的私钥的值。幸运的是,有一个简单的调整可以修复这个问题:

s i = k i + H ( X , R , m ) ∗ a i ∗ x i s_i = k_i + H(X, R, m)*a_i*x_i si=ki+H(X,R,m)aixi

个人理解:聚合私钥 x x x 本质上就是聚合公钥 X X X 的私钥,需要满足 x ∗ G = X x*G=X xG=X 这一关系。这里 X i X_i Xi 乘以 a i a_i ai 这一权重后导致 X X X 发生了改变,那么 x i x_i xi 也需要乘以相应的权重,以保证 x x x 仍然是 X X X 的私钥。

这样我们就恢复了我们的聚合签名:

s = s 1 + s 2 + . . . + s n = ( k 1 + . . . + k n ) + H ( X , R , m ) ∗ ( a 1 ∗ x 1 + . . . + a n ∗ x n ) = k + H ( X , R , m ) ∗ x \begin{alignat}{2} s &= s_1 + s_2 + ... + s_n \\ &= (k_1 + ... + k_n) + H(X, R, m)*(a_1*x_1 + ... + a_n*x_n) \\ &= k + H(X, R, m)*x \end{alignat} s=s1+s2+...+sn=(k1+...+kn)+H(X,R,m)(a1x1+...+anxn)=k+H(X,R,m)x

回顾一下,MuSig 签名过程包括三个阶段:

  1. 所有签名者发送承诺 t i t_i ti
  2. 所有签名者揭示随机数 R i R_i Ri,并且所有签名者验证 t i = H ( R i ) t_i = H(R_i) ti=H(Ri)
  3. 所有签名者计算并发送他们的部分签名 s i s_i si

最后,任何所有签名者都可以计算并使用普通 Schnorr 签名 ( R , s ) (R, s) (R,s)

什么是承诺?答:承诺全称密码学承诺,是一个密码学概念,主要用于防止发送者撒谎。



5 未来展望

这是本文中证明安全的 MuSig 提案,但许多人对需要 3 个往返通信的要求不满意,并且已经有很多工作致力于消除一个交互性的回合,以制作一个只有 2 个回合的 MuSig 版本。参见 Jonas Nick 的这篇博客文章,了解为什么将 3 个回合协议缩短为 2 个回合协议的各种捷径是不安全的。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/559338.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++奇迹之旅:深入理解赋值运算符重载

文章目录 📝赋值运算符重载🌠 运算符重载🌉特性 🌠 赋值运算符重载🌠传值返回:🌠传引用赋值:🌉两种返回选择🌉赋值运算符只能重载成类的成员函数不能重载成全…

用Gold-yolo模块改进yolov8模型

gold-yolo论文: https://arxiv.org/pdf/2309.11331.pdf gold-yolo代码: https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 一 gold模块简介 Gold-Yolo是华为诺亚方舟实验室2023年发布的工作,主要优化检…

Linux程序的地址空间,进程终止

个人主页:点我进入主页 专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂 一.程序的地址空间 1.1程序的地址空间的引入 我们知道frok可以创建…

重塑我们对随机性在计算中的作用的理解

2023年图灵奖,最近刚刚颁给普林斯顿数学教授 Avi Wigderson!作为理论计算机科学领域的领军人物,他对于理解计算中的随机性和伪随机性的作用,作出了开创性贡献。 Avi Wigderson 的履历 自 1999 年以来,Wigderson 一直担…

Python五子棋VS人机对战

上一次编写了一个python五子棋游戏,但是属于玩家之间的对战。今天介绍五子棋和人机对战。本博文目的是教学和一些毕业设计。 目前电脑下棋逻辑算法还是比较简单的,不能和市面上五子棋相提并论,请大家理想对待! 代码: import pygame import sys import tkinter as tk fro…

再拓信创版图-Smartbi Insight V11与东方国信CirroData数据库完成兼容适配认证

近日,思迈特商业智能与数据分析软件 [简称:Smartbi Insight] V11与北京东方国信科技股份有限公司 (以下简称东方国信)CirroData-OLAP分布式数据库V2.14.1完成兼容性测试。经双方严格测试,两款产品能够达到通用兼容性要…

python语言零基础入门——注释、print()函数、input()函数

目录 一、注释 1.块注释 2.行内注释 3.多行注释 二、打印变量 1.print()函数:输出/打印指定内容 2.input()函数:输入指定内容 三、编程题:个人名片 一、注释 1.块注释 以#开始,直到本行结束都是注释为了保证代码的可读性…

初步学习node.js文件模块

环境已安装好; 写一个read1.js如下; var fs require("fs"); var data ;// 创建一个流 var stream1 fs.createReadStream(test1.jsp); stream1.setEncoding(UTF8);// 绑定data事件 stream1.on(data, function(mydata) {data mydata; });/…

Unity ECS

一:前言 ECS与OOP不同,ECS是组合编程,而OOP的理念是继承 E表示Entity,每个Entity都是一个有唯一id的实体。C表示Component,内部只有属性,例如位置、速度、生命值等。S表示System,驱动实体的行为…

Leetcode. 12 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例…

原来我一直被骗了!Burp suite诱导劫持攻击【附工具】

一、点击劫持 点击劫持是一种基于界面的攻击,用户通过点击诱饵网站中的一些其他内容被诱骗点击隐藏网站上的可操作内容。举例来说,一个网络用户可能会访问一个诱饵网站(可能是通过电子邮件提供的链接),并点击一个按钮以…

C语言---贪吃蛇(二)---逻辑和代码的实现

文章目录 前言1.准备工作2.蛇的相关属性3.游戏流程设计3.1.游戏开始(GameStart)3.1.1.设置光标位置3.1.2.隐藏光标3.1.3.打印欢迎界面3.1.4.创建地图3.1.5.初始化蛇身3.1.6.创建食物 3.2.游戏运行(GameRun)3.2.1.打印信息栏3.2.2.蛇身的移动3.2.2.1.判断下一个结点是否为食物3.…

【Linux】iptables的应用

iptables 防火墙 防火墙是一种网络安全系统,它位于内部网络与外部网络(如互联网)之间,通过实施预定义的安全策略来控制网络间的通信。防火墙的主要目标是保护内部网络资源免受未经授权的访问、攻击或潜在威胁,同时允…

FFmpeg源码编译

msys2 依赖环境安装 依赖环境安装编译X264编译 fdk-aac文件处理编译x265编译FFmpeg 依赖环境安装 编译X264 用于h264 AVC视频格式编码 CCcl ./configure --enable-shared #指定使用cl,编译成动态链接库 make -j32 #使用32线程进行编码 make install命令一 关于第一条命令执…

VUE的import store from ‘./vuex/store改为‘ import store from ‘./vuex/store.js‘

ERROR Failed to compile with 1 error 下午5:25:40 error in (webpack)-dev-server/client?http://10.18.173.180:8081/sockjs-node Syntax Error: no such file or directory, open D:\4myroom\H…

2024年,新手做抖店千万犯这几点错误,轻则保证金,重则封店!

哈喽~我是电商月月 很多做抖音小店的新手朋友都忽略了违规操作这一部分,交完保证金以为后续不开了保证金还能退回?别天真了! 不了解抖音小店的行为规则,违规了不仅保证金没了,严重的话,店铺都开不下去&am…

【精简改造版】大型多人在线游戏BrowserQuest服务器Golang框架解析(2)——服务端架构

1.架构选型 B/S架构:支持PC、平板、手机等多个平台 2.技术选型 (1)客户端web技术: HTML5 Canvas:支持基于2D平铺的图形引擎 Web workers:允许在不减慢主页UI的情况下初始化大型世界地图。 localStorag…

谷雨,春天的最后一次回眸

人生并不像火车要通过每个站似的经过每一个生活阶段。 今日谷雨,这不是技术文,是码哥的碎碎念 谷雨猕漫着芭蕉的味道动了心成了情白素贞的姻以伞结缘可天若无雨地上无伞断桥未断过客,能留下一段传奇吗?或许难难 倘若在江城边不是西…

盲人购物指南:智能化辅助引领超市购物新体验

作为一名资深记者,我有幸见证了一位盲人朋友借助一款名为蝙蝠避障的高科技辅助应用,独立完成超市购物之旅,这一过程充分展示了盲人购物指南新时代的到来。 在前往超市的路上,这款应用犹如一位贴心的“电子向导”,实时为…

编程范式之函数编程

文章目录 **核心概念****特征****优点****示例语言**案例 函数编程(Functional Programming, FP)是一种编程范式,它强调程序由一系列不可变的值和纯函数(Pure Function)组成,尽量避免副作用(Sid…