RSA的加密规则:m^e≡c(mod n),即c=m^e%n
RSA的解密规则:c^d≡m(mod n),即m=c^d%n
其中:m为明文,c为密文,ed≡1(mod φ(n)),(n,e)构成公钥,(n,d)构成私钥
撇除密钥的生成,RSA加密解密的核心就一个:快速幂取模算法
快速幂取模算法类似于快速幂算法,但要复杂一点。
//递归法
function quick1($a, $b, $c)
{
if($b==1) return $a % $c;
$temp = quick1($a, $b>>1, $c);
return ($b&1)==0?($temp*$temp)%$c:($temp*$temp*$a)%$c;
}
//蒙哥马利法
function quick2($a, $b, $c)
{
$ans = 1;
$a = $a % $c;
while($b != 0)
{
if(($b & 1) ==1)
{
$ans = ($ans * $a) % $c;
}
$b>>=1;
$a = ($a * $a) % $c;
}
return $ans;
}
算法原理
先了解两条模运算性质:
- 递归法原理
当b为偶数时:
当b为奇数时
经过以上推导,高次幂的求模降为低次幂的求模了,而降幂的规律,不管b的奇偶,刚好符合二进制移位,并且最终都会降到易于求解的1次幂,即a mod c。
- 蒙哥马利法原理(递推)
b可用以下二进制形式表示
那么
令
结合前面模的积运算性质,则有
又令
则有
bn只有0、1两个取值,所以
再令
则有
综上所述:An为所求目标,可通过An-1递推求得,递推中还需Kn,而Kn和bn有关,当bn=0,Kn=1;当bn=1,Kn=Tn,Tn也可以通过Tn-1递推求得。
递推初始条件
这里之所以是T1而非T0,是因为T0无实际意义,而且需要开方,不方便计算。至于改变后迭代的变化参看后面的代码。
下面看代码
int quick(int a,int b,int c)
{
//An,初始值A0
int A=1;
//Tn,初始值T1
T=a%c;
while(b!=0)
{
//这个if是判断目前最右边的一位bn是不是1
//如果是1,那么Kn=Tn直接用Tn递推,具体看上面原理
//如果是0,那么Kn=1,考虑到An-1是小于c的,所以An = (An-1*Kn)%c = An-1,就是说可以不用更新An了
if(b&1) {
A = ( A * T ) % c;
}
//二进制位移,再结合if条件的位与运算,相当于从右到左读取位b1 b2 b3 b4等等
b>>=1;
//更新Tn,供下一轮计算An使用
//本来应该在An之前计算的,但由于初始值是T1开始的,所以先用再算
//因为b的二进制的任何位置是都有可能为1的,所以我们需要一直计算Tn,不能放到if里面
//另外观察代码可知,局部变量a只在第二行处用到,为减少空间分配,文章开头及网上的一些实现方法,用a替换了T
T=(T*T)%c;
}
return A;
}
参考文章:https://blog.youkuaiyun.com/qq_36760780/article/details/80092665