前言
因为我们的主要目的还是讲解如何实现通用的多签方案,所以这里不会非常细致的讲解ED25519的各种优缺点,以及各种细节内容,主要是希望在讲解多签之前,大家对这个算法有个简单的认知。
首先ED25519是EDDSA的一种特殊实例。类似secp256k1之于ECDSA。
他的椭圆曲线公式如下
−x2+y2=1−121666121665x2y2
公私钥对生成
25519的公私钥生成与256k1有一些不同,步骤如下:
- 生成私钥:k=rand(N)
- 计算私钥哈希值:H(k)=(h0,h1,...,h2b−1)
- 生成整数: a=2b−2+∑3⩽i⩽b−32ihi∈{2b−2,2b−2+8,...,2b−1−8}
- 生成公钥: A=aB
B 是基点。
这里H(k) 是对k进行sha256运算。
可以看到,这里的a,更像是我们认知里的私钥,这里我们先不展开,后续多签讲解的时候会再继续聊。
签名过程
- 生成随机数: r=H(hb,...,h2b−1,M)
- 计算R: R=rB
- 计算S: S=r+H(R,A,M)a
则签名就是 (R,S)
签名验证
验证 RB=rB+H(R,A,M)aB=R+H(R,A,M)A 是否成立
以上就是25519的基础知识,部分地方可能不够详细,大家可再自行查阅。
MPC
在讲如何使用MPC对25519签名进行分解之前,我们先回看下整个签名和验签的过程,会发现以下几点:
- a的生成算法,对于整体签名和验签并无影响,也就是说,a完全可以通过随机数随机生成后,简单调整即可。
- 随机数r的生成,25519的定义里采用了一个确定性随机数算法,当私钥和消息确定时,r也就确定了,但是后续的过程中我们可以看到: r如何产生的,后续的过程并不关心。我们只要保证r不泄漏,并且不重复使用即可(如果重复或者泄漏,会造成a被攻破)。
根据以上两点,ZenGo在具体实现过程中进行了一些变更,与协议并不完全贴合。具体实现步骤如下:
- 私钥的生成
- 各方分别生成公私钥和随机数 ki=rand(N),H(ki)−>[ai,pi],Ai=aiB
- 将ai通过秘密分享的方式,各方进行交换(秘密分享的内容可参考ECDSA Generate部分的讲解),将得到的秘密进行加和,得到xi。对应的多签公钥则是,A=∑Ai
- 签名计算
- 参与签名的各方分别进行随机数计算 ri=H(pi,m,rng),Ri=riB 这里就与标准协议有所不同了,引入了随机数rng。随后各方通过秘密分享的形式将ri进行分解,各方得到noncei。这里需要注意的一点就是,这里进行秘密分享时,只有参与签名的各方会加入。同样我们可以得到 R=∑Ri;
- 各方继续分别计算 si=noncei+H(R,A,m)xi
- 最后我们收集各方签名,然后通过拉格朗日插值法,就可以得到S=largrange(si)。最终签名(R,S)