在众多的加密算法中都需要进行幂的取模运算,比如在RSA算法中需要计算ne mod N,我们称之为幂模算法,其中:
其中n,e都是非常大的数,这样计算ne mod N就需要一些新方法,其计算方式也关系到RSA的效率问题。
对一般的幂模运算:ab mod m,存在下面三种算法:
先计算ab,再取模,这样很容易益处,在实际中基本不可行
设c是a除以m的余,即c=a-k*m,也可用同余表达式a≡c (mod m)表示,则可以证明:
对任意整数b
ab≡bc (mod m) -----------(1)
证明:
c=a mod m <=> a = km +c
=>ab = k*b*m+bc => ab mod m = (k*b*m + bc)mod m = bc mod m
(1)式等价于:ab mod m =b* (a mod m) mod m,这非常适合递归计算。
a≡c (mod m) => a2≡c2 (mod m)--------------(2)
证明:
a=k*m+c =>a2=(km)2+2ckm+c2 =>a2 mod m =c2 mod m,即(2)成立
特别地对幂取模计算可以递归使用(1)式
int mod(int a,int b,int m){ int result = 1; for(int i=0;i<b;i++) { result = (result*a) %m; } return result; }如果指数b不大,上述方法很有效。但如前所述,一般在RSA算法中的指数b会很大(可以超过1024位),对如此巨大的一个数字做循环计算,时间开销将是不能接受的,因此需要继续从理论上挖掘计算幂取模的算法。
进一步研究指数b的二进制表示发现,对任意的整数b都可表示为:
因此,ab可表示为:
即用b的每一位表示a的每一项,而对任意相邻的两项存在平方关系,即:
因此我们构造下面的算法:
代码如下:
int mod(int a,int b,int m){ int result = 1; int base = a; while(b>0){ if(b & 1==1){ result = (result*base) % m; } base = (base*base) %m; b>>>=1; } return result; }
该方法是许多西方数学家努力的结果,通常也称为Montgomery算法。
【1】http://en.wikipedia.org/wiki/Modular_exponentiation
【2】初等数论