AlexiaChen.github.io icon indicating copy to clipboard operation
AlexiaChen.github.io copied to clipboard

Ed25519签名与Schnorr签名

Open AlexiaChen opened this issue 4 years ago • 0 comments

之前其实写了一篇《深入了解Ed25519》, 主要介绍了背景及来龙去脉,最后给了用Python实现的算法,没有列出签名公式。公式会更清晰些,这里补一下。

Ed25519的签名公式与Schnorr签名很像,可以理解为在扭曲爱德华曲线上用了Schnorr机制的签名,是Schnorr的变种,也继承了Schnorr的优点,就是相比ECDSA非常方便做门限化多签。

Ed25519就是EdDSA标准的具体实现了,有性能高,更安全等这些优点。经过 NIST 批准的曲线有多条,例如 secp256r1,secp256k1 等。但现有的 ECC 算法中的曲线被指存在后门。但是Ed25519采用的扭曲爱德华曲线参数完全公开,并说明了参数选取的意义,保证曲线中并未内置后门。同时 ED25519 采用 Schnorr 机制作为签名的构建方式,使得签名与验证的性能得到了巨大的提升。

具体算法

公私钥对的生成

首先公私秘钥长度为b,为256-bit, 生成元为G,Hash函数为SHA512, M是被签名的消息, l是一个大素数, 满足l.G = O , 就是对G点的标量乘法得到的是无穷远点,也就是I是曲线上子群的阶。设私钥为sk, 公钥为pk。

  • 随机生成一个长度为256-bit的二进制数据作为私钥sk
  • 对sk进行Hash,也就是 Hash(sk), 产生了一个长度为2b的512-bit的输出数据h。其中低256-bit的数据x用于产生公钥(h_0到h_(b - 1)), 另外的高256-bit的数据为随机数k(h_b 到h_(2b-1))
  • 将x_0 x_1 x_2的位设置为0,x_(b-1)的位设置为0, x_(b - 2)的位设置为1
  • 最后通过标量乘法计算公钥 pk = x.G

通过上面的步骤看到了吗?与平时接触到的椭圆曲线不一样,平时的椭圆曲线的公私钥就是pk = sk.G。而这里的公私钥生成却对标量做了处理,不是直接使用私钥做为G点标量乘法的标量。

签名流程

进行签名时,需要用到上一步生成的私钥sk,公钥pk的步骤中得到的随机数k。

  • 计算随机数r = Hash(k || M) (Schnorr签名中的r是随机生成的,这里的r用了Hash充当随机预言机来生成,也就是通过随机生成的秘钥sk来Hash后的随机数再Hash来生成的)
  • 计算随机点 R = G^r
  • 计算challenge c, c = Hash(R || pk || M)
  • 计算s, s = ( r + c*x ) mod l。
  • 生成签名数据(R, s)

验签流程

Verifier只需要知道公钥pk, 还有(R, s), 消息M本身就可以验证签名是否正确,公式如下:

c =  H(R || pk || M)
G^s = R + c*pk

总结

其实你可以发现,Ed25519的签名和验证流程几乎就是Schnorr签名的变种,但是随机数r没有像Schnorr那样采用本地的伪随机数生成器(PRG)生成,而是经过了sk私钥两次Hash的结果生成的,即随机数r已经完全脱离对随机数发生器(PRG)的依赖,避免了因为随机化问题而导致密钥的泄露与安全性问题。Hash函数的输出的随机肯定是与PRG不一样的,这个密码学Hash函数在这里充当了随机预言机,在统计上是随机的。

References

  • https://github.com/jedisct1/libsodium/issues/170
  • https://soatok.blog/2022/05/19/guidance-for-choosing-an-elliptic-curve-signature-algorithm-in-2022/
  • https://cendyne.dev/posts/2022-03-06-ed25519-signatures.html
  • https://rebase.network/posts/700

AlexiaChen avatar Jan 14 '21 03:01 AlexiaChen