密码学 | 数字签名方法:Schnorr 签名

⚠️原文:Introduction to Schnorr Signatures
⚠️写在前面:适用于有一点密码学基础的亲故,否则建议跑路。



1 Schnorr 签名的定义

假设你有密钥对 ( x , X = x ∗ G ) ( x, X = x * G ) (x,X=xG),那么消息 m m m 的 Schnorr 签名 ( R , s ) ( R, s ) (R,s) 为:

R = k ∗ G R = k * G R=kG s = k + H ( R , m ) ∗ x s = k + H( R, m )* x s=k+H(R,m)x

其中 k k k 是随机私钥。

这里作者假定你已经有一点密码学基础了,以防万一,还是说明一下 x x x 是私钥, X X X 是公钥。

让我们分解一下上述过程。

  1. 对于每个签名,签名者都会生成一个随机值 k k k,它是该签名的 一次性私钥
  2. 签名者计算 R R R,即 k k k 的公钥,称 R R R 为随机数(nonce value);
  3. 签名者计算 R R R 和消息 m m m 的哈希值,这个哈希值是实际要签名的内容;
  4. 签名者将该哈希值乘以自己的私钥 x x x,再加上一次性私钥 k k k,得到 s s s

每个签名由一个 ( R , s ) (R, s) (R,s) 对组成: s s s 本质上是 “私钥 x x x 的所有者已签署消息 m m m” 的证明,而 R R R 作为一次性公钥,主要用于和普通公钥 X X X 一起验证该签名。

在比特币中,一个 ( R , s ) (R, s) (R,s) 对使用 64 个字节进行编码,其中前 32 个字节表示 R R R,后 32 个字节表示 s s s

一旦生成签名,任何知道消息 m m m 和公钥 X X X 的人都能够验证该签名。签名验证只是检查:

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

你会注意到:消息 m m m 和公钥 X X X 必须是已知的,或者是被提供给了验证者的,而 R R R s s s 是作为签名给出的。



2 Schnorr 签名的属性

Schnorr 签名看起来像随机数。

具体来说,值 k k k x x x 是随机数, H ( R , m ) H(R, m) H(R,m) 也是随机数,因为它是哈希函数的输出。宽松地说,将一堆随机数放在一起,得到的还是一个随机数。总之,无论消息是什么以及签名者是谁,值 s s s 都同样可能是任何数字。

请注意,此论点并不能证明 Schnorr 签名不会泄漏有关签名者密钥的信息,我们将在稍后讨论安全性时讨论此属性。

禁止重复使用随机数!

我将密钥 k k k R R R 称为 “一次性的” 是有原因的:如果你使用相同的密钥签署两条不同的消息,你将泄露整个私钥。让我们看看如果你犯了这个错误,攻击者是如何窃取你的密钥的。

攻击者首先获取到:

  • X X X:你的公钥
  • R R R:你不小心重用了的随机数
  • m 1 m_1 m1:你签署的第一条消息
  • s 1 s_1 s1:你生成的第一个签名
  • m 2 m_2 m2:你签署的第二个消息
  • s 2 s_2 s2:你生成的第二个签名

回想一下, s s s 值是对消息 m m m 和私钥 x x x 的承诺,由随机数 k k k 调整。因此,如果攻击者将两个 s s s 值相减,用于隐藏私钥 x x x 的随机调整将被抵消。

重用随机数 R = k ∗ G R=k*G R=kG 意味着两次签名所用的随机数 k k k 是相同的,本质上就没有进行随机调整了。

攻击者计算:

s 1 − s 2 = ( k + H ( R , m 1 ) ∗ x ) − ( k + H ( R , m 2 ) ∗ x ) = H ( R , m 1 ) ∗ x – H ( R , m 2 ) ∗ x = ( H ( R , m 1 ) – H ( R , m 2 ) ) ∗ x \begin{alignat}{2} s_1 - s_2 &= ( k + H( R , m_1 )* x ) - ( k + H( R , m_2 )* x ) \\ &=H( R , m_1 )* x – H( R , m_2 )* x \\ &= (H( R , m_1 ) – H( R , m_2 ))* x \end{alignat} s1s2=(k+H(R,m1)x)(k+H(R,m2)x)=H(R,m1)xH(R,m2)x=(H(R,m1)H(R,m2))x

正如我所说, k k k 值实现的随机调整抵消了,只留下 H ( . . . ) ∗ x H(...)*x H(...)x 值的差异,它只是两个哈希值差异的 x x x 倍。除此之外,这两个哈希值还都是已知的,因为它们是公共信息的哈希。

因此攻击者可以求解 x x x

x = ( s 1 − s 2 ) ∗ ( H ( R , m 1 ) − H ( R , m 2 ) ) − 1 x = ( s_1 - s_2 )*(H( R , m_1 ) - H( R , m_2 )) ^{-1} x=(s1s2)(H(R,m1)H(R,m2))1

BIP 340 尝试通过将消息 m m m 用作生成密钥 k k k 的密钥生成函数的一个输入,以确保不会发生随机数重用。因为如果消息 m m m 改变,随机数 k k k 也会跟着改变。

这两个属性同样适用于 ECDSA 以及许多其他签名协议,实际上,它们是 Schnorr 签名安全性不可或缺的一部分。



3 与 ECDSA 比较

ECDSA 和 Schnorr 之间的两个主要区别使得 Schnorr 签名独特且更优越:

  • Schnorr 签名比 ECDSA 签名更小、更快。比特币中使用的 ECDSA 签名长度为 70 或 71 字节,而 Schnorr 签名仅为 64 字节。此外,Schnorr 签名的生成和验证明显快于 ECDSA 签名。
  • Schnorr 签名是线性的。这是将 Schnorr 与其他签名方案区分开来的关键区别。

线性是签名函数 Sign 的属性,该属性说明:

S i g n ( x 1 , k 1 , m ) + S i g n ( x 2 , k 2 , m ) = S i g n ( x 1 + x 2 , k 1 + k 2 , m ) Sign(x_1, k_1, m) + Sign(x_2, k_2, m) = Sign(x_1 + x_2, k_1 + k_2, m) Sign(x1,k1,m)+Sign(x2,k2,m)=Sign(x1+x2,k1+k2,m)

上述等式说明,如果两个实体签署同一条消息,然后将它们的签名相加,我们最终将得到它们聚合密钥的有效签名!

签名函数 Sign 是一个接受私钥 x x x 和消息 m m m 作为输入并输出部分签名 s s s 的函数。

通过修改 Schnorr 签名的版本来验证 “Schnorr 签名是线性的”。具体来说,令聚合随机值 R = R 1 + R 2 R = R_1 + R_2 R=R1+R2,即每个随机值 R i R_i Ri 的和。

什么叫做 “修改 Schnorr 签名的版本”?答:因为 H ( R 1 , m ) H(R_1,m) H(R1,m) H ( R 2 , m ) H(R_2,m) H(R2,m) 是没有办法相加的,所以我们换做使用 H ( R , m ) H(R,m) H(R,m),其中 R R R R 1 R_1 R1 R 2 R_2 R2 的和,以此来实现相加😇

将两个实体的签名相加:

S c h n o r r S i g n ( x 1 , k 1 , m ) + S c h n o r r S i g n ( x 2 , k 2 , m ) = ( k 1 + H ( R , m ) ∗ x 1 ) + ( k 2 + H ( R , m ) ∗ x 2 ) = ( k 1 + k 2 ) + H ( R , m ) ∗ ( x 1 + x 2 ) = S c h n o r r S i g n ( x 1 + x 2 , k 1 + k 2 , m ) \begin{alignat}{2} SchnorrSign(x_1, k_1, m) &+ SchnorrSign(x_2, k_2, m) \\ &= (k_1 + H(R, m)*x_1) + (k_2 + H(R, m)*x_2) \\ &= (k_1 + k_2) + H(R, m)*(x_1 + x_2) \\ &= SchnorrSign(x_1 + x_2, k_1 + k_2, m) \end{alignat} SchnorrSign(x1,k1,m)+SchnorrSign(x2,k2,m)=(k1+H(R,m)x1)+(k2+H(R,m)x2)=(k1+k2)+H(R,m)(x1+x2)=SchnorrSign(x1+x2,k1+k2,m)

我们修改了 Schnorr 签名以使用相同的哈希,从而得到了一个很好的线性签名函数。

请注意,ECDSA 是没有这个属性的。

最后,正如 BIP 340 中所说:“尽管有这些优势,几乎没有缺点。” Schnorr 是基于椭圆曲线的最简单的签名方案,比特币将只会从它中受益。

好硬核的机翻💥



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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

吴恩达机器学习笔记 三十五 异常检测与监督学习

什么时候选择异常检测? 正样本 ( y 1 ) 的数量非常少 负样本 ( y 0 ) 的数量非常多 有很多不同的异常,现有的算法不能从正样本中得知什么是异常,或未来可能出现完全没见过的异常情况。 例如金融欺诈,隔几个月或几年就有新的…

java+idea+mysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码

javaideamysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码 随着人工智能技术的快速发展,语音识别与自然语言理解技术的成熟应用,基于人工智能的智能导诊导医逐渐出现在患者的生活视角中,智能导诊系统应用到医院就医场景中&#xff0c…

jvm-接口调用排查

问题描述 线上碰到个问题,某个接口调用时间特别长,线上调用接口直接报gateway time out 分析处理 1、先关闭该功能 (该功能是非核心功能) 2、本地起服务连环境排查,发现本地正常。并且线上其他接口正常,…

机器学习笔记——浅析L2,1范数正则化的线性回归

前言 嘻嘻,刚开始搓逾期了快两周的线性回归实验报告,为了让报告稍微不那么平淡不得不啃论文。 本文从最基本的线性回归开始,对比不同正则化方法的特点和作用,推广到多任务问题并引出L2,1范数正则化,卑微小采购尝试去…

顺序表复习(C语言版)

数据结构是什么? 数据结构就是为了把数据管理起来,方便我们的增删查改 数据结构是计算机存储、组织数据的方式 数组就是一种最基础的数据结构 顺序表是什么? 顺序表就是数组 Int arr[100] {1,2,3,4,5,x,……} 修改某个数据&#xff1a…

【leetcode面试经典150题】56. 基本计算器(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

Mac下删除旧版本.net sdk

参照微软官网给的方法,Releases dotnet/cli-lab (github.com) 好像不能直接的解决问题,我做一下补充,希望对需要删除旧版本sdk的小伙伴们有所帮助 1:下载工具包 Releases dotnet/cli-lab (github.com) 2:打开终端,cd切换到该文件的制定目录 3:然后按照提示一步步执行…

mybatis使用

mybatis使用 一、添加配置文件 在application.properties配置文件文件中添加数据库连接信息 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.urljdbc:mysql://localhost:3306/your_database_name?useUnicodetrue&characterEncodingUTF-…

java核心类

一,String字符串 1.1,String字符串是引用类型,且不可变 String str1 "Hello";String str2 str1.concat(" World"); // 使用concat方法连接字符串,返回一个新的字符串对象System.out.println(str1); // 输出:Hello,原始…

C语言:复习

文章目录 思维导图数组和指针库函数的模拟实现判断大小端 最近知识学的差不多了,因此开始复习,本篇开始的是对于C语言的复习 思维导图 下面就依据下图,进行内容的整理 数组和指针 这个模块算是C语言中比较大的一个模块了,具体概…

IO——线程

1. 什么是线程 1.1概念 线程是一个轻量级的进程,为了提高系统的性能引入线程。 线程和进程都参与统一的调度。 在同一个进程中可以创建的多个线程, 共享进程资源。 (Linux里同样用task_struct来描述一个线程) 1.2进程和线程的区别 相同点…

【Vue】Vue中使一个div铺满全屏

在Vue中实现div全屏铺满的方式与纯CSS实现类似&#xff0c;只是在Vue组件中应用CSS的方式略有不同。 最近在项目开发中&#xff0c;就遇到了这个问题&#xff0c;特此记录一下&#xff0c;方便大伙避坑。 有这么一段代码&#xff1a; <template><div class"fu…

JS - 在JS中常用的运算符

学过编程语言的都知道一种大部分编程语言其实都存在许多相似的地方&#xff0c;比如数学中的四则运算&#xff0c;这个在JS中同样生效&#xff0c;不过在JS中&#xff0c;有进行部分拓展&#xff0c;这个也是其他语言中都有的&#xff0c;每个语言都有其功能和特性&#xff0c;…

流媒体协议--RTMP

文章目录 RTMP播放基本流程TCP握手过程RTMP握手过程connect连接createStream 创建流play 播放命令deleteStream删除流RTMP数据组成 RTMP(Real Time Messaging Protocol)是一个应用层协议&#xff0c;主要用于在Flash player和服务器之间传输视频、音频、控制命令等内容。 该协议…

类和对象-对象特性-类对象作为类成员

类对象作为类成员 #include<iostream> #include<string> using namespace std; class Phone{ public:Phone(string pName){m_pNamepName;}string m_pName; }; class Person{ public:Person(string name,string pName):m_Name(name),m_Phone(pName){}string m_Nam…

【笔试强训_Day06】

文章目录 1.字符串相乘 1.字符串相乘 题目链接 解题思路&#xff1a; 高精度乘法&#xff0c;注意要学会下面这种列式相乘的形式&#x1f34e; 注意细节❗&#xff1a; ① &#x1f34e; 首先把列式相乘的数据都存放到数组中去&#xff0c; 然后再对数组中的数据进行取余进…

C++:运算符重载和“const”成员

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;运算符重载》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 文章目录 赋值运算符重载1. 运算符重载2.赋值运算符重载第一个点第二个点&…

迅雷下载不了的资源怎么下载?

我想下载Boost库&#xff0c;但是下载不下来 用迅雷下载是一直卡在0k 后来尝试在centos上用wget进行下载&#xff0c;竟然可以 wget https://boostorg.jfrog.io/artifactory/main/release/1.85.0/source/boost_1_85_0.tar.gz

揭开ChatGPT面纱(一):准备工作(搭建开发环境运行OpenAI Demo)

文章目录 序言&#xff1a;探索人工智能的新篇章一、搭建开发环境二、编写并运行demo1.代码2.解析3.执行结果 本博客的gitlab仓库&#xff1a;地址&#xff0c;本博客对应01文件夹。 序言&#xff1a;探索人工智能的新篇章 随着人工智能技术的飞速发展&#xff0c;ChatGPT作为…

go 语言 mage 安装踩坑

具体安装代码&#xff1a;mage 官方地址&#xff1a;Mage :: Mage git clone https://github.com/magefile/mage cd mage go run bootstrap.go 在go部署完后&#xff0c;执行上面的脚本&#xff0c;发现最后一句老是执行不成功&#xff1a; rootBDGF-7FPQW93:/home/gw00241401…