看了很多关于比特币签名算法的文章,遂进行整理,简化记录下。
以下的计算都是基于椭圆曲线有限域所做,所以阅读以下内容前,需要对椭圆曲线与有限域有一定的了解。
椭圆曲线签名(ECDSA)
签名
\(R=k*G=(r,y)\) // \(k\)是我们取的随机值,\(G\)是椭圆曲线的基点
\(z=Hash(m)\) // \(m\)是待签名的信息
\(S=\frac{z+r*G}{k}\) // \(G\)是椭圆曲线的基点,\(r\)是\(R\)的x点坐标
\(P=p_k*G\) // \(P\)是公钥,\(p_k\)是私钥
\(\delta=(r,S)\) // \(\delta\)是签名的输出
验证
求 \(\frac{z}{S}*G+\frac{r}{S}*P=(r',y')\)
校验 \(r'\)是否等于\(r\)
原理
\(\frac{z}{S}*G+\frac{r}{S}*P \)
\(=\frac{z}{\frac{z+r*p_k}{k}}*G+\frac{r}{\frac{z+r*p_k}{k}}*(p_k*G) \)
\(=\frac{z*k*G}{z+r*p_k}+\frac{r*k*p_k*G}{z+r*p_k} \)
\(=\frac{k*G(z+r*p_k)}{z+r*p_k} \)
\(=k*G\)
\(=R=(r',y')\)
所以签名如果是正确的话,那么\(r'=r\)
关键点在于:通过私钥\(p_k\)加密的数据只能公钥来解密,即如果可以通过公钥来解密,就可以确定私钥在输出签名的人手中。
Schnorr签名算法
签名
\(P=p_k*G\) // \(P\)是公钥,\(p_k\)是私钥
\(R=k*G\) // \(k\)是我们取的随机值
\(e=Hash(R||m)\) // \(m\)是待签名的信息
\(S=k+e*p_k\) // \(G\)是椭圆曲线的基点
\(\delta=(R,S)\) // \(\delta\)是签名的输出
验证
校验 \(S*G\)是否等于 \(R+e*P\)
原理
\(S*G \)
\(=(k+e*p_k)*G \)
\(=k*G+e*p_k*G \)
\(=R+e*P \)
两者的比较
比特币的加密算法从ECDSA转换为Schnorr,客观层面是因为Schnorr签名算法的专利到期了,可以放心用了。技术层面则是因为Schnorr签名使用的字段更少,且更适用于多签的情况。比特币进行Taproot 升级的做法,无疑是想将比特币的脚本、签名、layer2等扩展出更多的可能性,而Schnorr签名多签的优势则给了社区升级签名算法的信心。
参考
[2] 区块链密码基础之签名算法(一)
文章评论