二次剩余

最近在做一些关于椭圆曲线的优化,其中message到点的映射需要用到二次剩余相关的知识,也是第一次接触相关算法,查了一些资料之后自己在GPU端实现了一下,记录一下相关的心得。

一个整数X的平方 X2X^{2} 除以另一个整数p的余数,就叫做X对于整数p的二次剩余。也就是当存在某个X使得

X2d(modp)X^{2} \equiv d (mod p)

则d就是模p的二次剩余。一般来说,p都是大素数。

当需要判断一个x是否在椭圆曲线上时,需要计算 y2=x3+ax+by^{2} = x^{3} +ax +b
是否成立,也就是算x3+ax+bx^{3} +ax +b是不是模p上的二次剩余

判断二次剩余

判断二次剩余可以用欧拉准则,但是欧拉准则也只能判断是不是,但是不能求解出具体的结果,用来验证足够了。

欧拉准则提出,d是模p的二次剩余的充要条件就是

d(p1)/21(modp)d^{(p-1)/2} \equiv 1 (modp)

d是模p的非二次剩余的充要条件就是

d(p1)/21(modp)d^{(p-1)/2} \equiv -1 (modp)

这里由于椭圆曲线域上的这个素数p都是提前知道的,所以我们可以预先算出来(p-1)/2,这样就可以方便的计算,省掉了很多计算的步骤。对于模幂操作可以用蒙哥马利模乘来实现模幂。

求解二次剩余

欧拉准则只能做判断,当判断这个x的坐标在椭圆曲线上时,我们需要求得y的坐标,所以还需要求解二次剩余,这里两种方法,一种是Tonelli-Shanks算法,我在程序中采用了这种方法(由于素数p满足其中的特殊条件),所以计算很快,只需要算一次模幂操作。。

Tonelli-Shanks

这个算法其实网上有很多的介绍,这里多介绍,只说我在实现的时候看到的特殊情况
算法开始部分如下

输入为模p的一个二次剩余d,我们想得到的则是这个二次剩余的解X,使得X2d(modp)X^{2} \equiv d (mod p)

1.首先我们先算p-1,之后设p1=Q2Sp-1=Q*2^S,也就是把p-1不停的除以2,除到结果为奇数为止。如果S=1,也就是p-1除以2为奇数(也可以表示为p-1不能被4整除),则直接返回X=±d(p+1)/4X=\pm d^{(p+1)/4}

到这里我们可以发现如果素数p不能被4整除,则可以很快的返回结果。其实也就是素数二进制的最后一位如果是11则不行,16进制则是最后一位是3,7,B,F.很多大素数都满足这几个条件,SECP256K1的曲线,还有国密的SM2曲线都满足这个,所以可以直接返回。
具体的算法的步骤可以百度,有超级超级多介绍的。

Cipolla

其实还有一种,按理来说这种应该再一般情况下比上一种更快。这种更简单

就是找到一个数a,使得a2na^{2}-n是模p下的非二次剩余,也就是(a2n)(p1)/21(modp)(a^{2}-n)^{(p-1)/2} \equiv -1 (modp)
由于二次剩余与非二次剩余的概率各是50%,所以这个数不难找,找到后令w=a2nw=a^{2}-n,也就是w是这个非二次剩余。

之后我们就可以计算x=(a+w1/2)(p+1)/2x=(a+w^{1/2})^{(p+1)/2}就是我们的解。

这个看起来很简单,几次模幂操作就可以完成。但是问题在于w1/2w^{1/2}也就是根号下w,他不是个整数,这个在我们整数域下没法表示。这个方法可以通过构造一个新的域。类比于复数的表示方法。

(a,b)=a+bw1/2(a,b) = a+b*w^{1/2}

之后类比复数定义加法和乘法就可以了。

其实我也是这些安全算法的初学者,因为要用GPU加速所以最近在搜索相关的资料,感觉还是很奇妙这些,其中也有很多小的奇技淫巧可以用,大大加快速度,还有好多东西要学。