Schnorr
签名基于有限域椭圆曲线, 与 ECDSA
类似, 但是 Schnorr
相对于 ECDSA
来说, 更快速, 并且可以实现多签聚合。
假设有通信双方 A 和 B, 已知椭圆曲线 Ep(a,b) 、基点 G、 G 的阶 n,要签名的消息 m。
A 生成自己的公钥和私钥,即从 {1,⋯,n−1} 随机选择一个数 kA 作为私钥,公钥 HA=kAG
A 签名过程如下:
- 在{1,⋯,n−1} 中选择一个数 k
- 计算点 R 的坐标: R=kG
- 将要签名的消息 m、公钥 HA、R 的 x 坐标组合进行哈希运算, 得到 e=Hash(Rx ∣∣ HA∣∣ m)modn
- 计算 s=k+e⋅kAmodn
最终签名结果是 (Rx,s)
计算 e 时, 使用的哈希函数通常是 Sha256
已知要签名的消息 m 、签名数据 (Rx,s)、A 的公钥 HA, B 验证过程如下:
- 计算哈希值 e=Hash(Rx ∣∣ HA∣∣ m)。
- 验证等式: sG=Rx+eHA 是否成立。
证明:
Rx+eHA=Rx+e⋅kAG=kG+e⋅kA⋅G=(k+e⋅kA)G
当 k+e⋅kA 结果等于 s 时, 则说明签名有效。
ECDSA
签名过程需要计算 k−1 求模逆元, 而 Schnorr
签名直接计算 s=k+e⋅kAmodn, 没有求逆运算, 运算速度更快
ECDSA
签名验证需要两次标量乘法 u1G 和 u2HA, 而 Schnorr
签名验证只需要验证 sG=R+eP, 运算过程更简单
Schnorr
支持多个签名聚合
Schnorr
另一个重要的特征是聚合签名。聚合签名用于将多个签名数据聚合成一个签名数据, 从而减少总签名数据的大小, 降低交易费用。
聚合签名的过程如下:
-
对于每一个签名的参与者使用同一种椭圆曲线和基点 G, 生成各自的私钥 km 和公钥 Pi。
-
每个参与者选择不同的随机数 ki, 并计算对应的 Ri=kiG
-
与单签不同的, 聚合签名计算 e 时需要每一个签名参与者的公钥聚合, 以及 Ri 聚合。公钥和 Ri 都是有限域椭圆曲线上的点。聚合最简单的方式是点加: 将 Pi 依次相加得到聚合公钥点 Pagg=∑Pi, 将 Ri 依次相加得到聚合点 Ragg=∑Ri
-
计算哈希值 e=Hash(Ragg ∣∣ Pagg∣∣ m)
-
每个签名的参与者使用各自的私钥 km 以及 选择的随机 ki 计算各自的 si=ki+e⋅kmmodn
-
计算聚合签名 sagg=∑simodn, 这里的加法是算术加法。
-
最终的聚合签名是 (Ragg,sagg)
验证聚合签名时, 只需验证等式 saggG=Ragg+ePagg 是否成立。
假设现有两个 ECDSA
签名数据:
-
r1=k1G, s1=k1−1(m+r1ku1)modn
-
r2=k2G, s2=k2−1(m+r2ku2)modn
聚合 r 和 s:
- ragg=r1+r2
- sagg=s1+s2=k1−1(m+r1ku1)+k2−1(m+r2ku2)modn
签名数据 (ragg,sagg)
问题在于 s 无法聚合。因为 s1 和 s2 中包含了 k1−1 和 k2−1 这样的求模逆元运算, 使签名具有非线性特征。
而在 Schnorr
签名中, 由于没有求模逆元运算, 则可以直接聚合 s。