蒙哥馬利算法

蒙哥馬利模乘運算(Montgomery Modular Multiplication)[1]與蒙哥馬利冪模運算(Montgomery power module)和蒙哥馬利約減運算(Montgomery model reduction)統稱蒙哥馬利算法(Montgomery Algorithm)

  • 蒙哥馬利模乘運算:\(ab mod N\)
  • 蒙哥馬利冪模運算:\(a^b mod N\)
  • 蒙哥馬利約減運算:\(ab^{-1} mod N\)

蒙哥馬利模乘

模乘是計算\(ab\pmod{N}\)。在普通計算模N時,利用的是帶餘除法,除法運算需要太多次乘法,計算複雜度較高,「蒙哥馬利模乘」的思想就是利用進製表示簡化除法運算,轉化成位運算

  • 蒙哥馬利形式(Montgomery form, Montgomery domain)

爲了計算\(ab\pmod{N}\),需要找到一個\(R\),然後使得\(\mathrm{a}^{\prime}\equiv\mathrm{aR}\pmod{\mathrm{N}},\mathrm{b}^{\prime}\equiv\mathrm{bR}\pmod{\mathrm{N}}\)

這個\(R\)不是隨便取的,需要滿足兩個條件:

  1. \(R = 2^k > N\) ,其中\(k\)是滿足條件的最小正數,這就能保證除以\(R\)就相當於右移\(k\)
  2. \(gcd(R,N)=1\),這就可以求出\(m\)

在計算\(ab\pmod{N}\)時需要利用「蒙哥馬利形式」。令\(X=a'b'\),可以設計一個函數\(REDC(X)=XR^{-1}\pmod{N}\),計算結果爲\(X_1=REDC(X)=a'b'R^{-1}\pmod{N}=abR\pmod{N}\),這樣再調用一次函數計算\(REDC(X_1)=X_1R^{-1}\pmod{N}\)就能得到結果\(ab\pmod{N}\)

這個函數\(REDC()\)就是蒙哥馬利約減算法,即求\(XR^{-1}\pmod{N}\)

所以蒙哥馬利模乘可以分三步進行計算:

  1. 將輸入\(aR^2,bR^2\)轉成蒙哥馬利形式,即\(aR=REDC(aR^2),bR=REDC(bR^2)\)
  2. 做一次標準乘法得\(abR^2=aR*bR\)
  3. 最後做一次REDC得\(abR=REDC(abR^2)\)
  4. 注意上面三個步驟返回的是蒙哥馬利形式的\(ab\),即\(abR\)。若需要轉換成正常形式的\(ab\),需要再做一次\(REDC\)\(ab=REDC(abR)\)

代碼實現

給出一個蒙哥馬利模乘的Python實現計算 (23456789*12345678)%123456789,注意程序裏面取\(R=2^{64}\), 所以\(mod R\)相當於取低64bit,\(/R\)相當於右移64bit

import math

class MontMul:
    """docstring for ClassName"""
    def __init__(self, R, N):
        self.N = N
        self.R = R
        self.logR = int(math.log(R, 2)) #log_2 ^ R
        N_inv = MontMul.modinv(N, R)
        self.N_inv_neg = R - N_inv    #N_inv_neg=R-N^{-1}
        self.R2 = (R*R)%N

    @staticmethod        
    def egcd(a, b):
        if a == 0:
            return (b, 0, 1)
        else:
            g, y, x = MontMul.egcd(b % a, a)
            return (g, x - (b // a) * y, y) #g=gcd(a,b)

    @staticmethod
    def modinv(a, m):
        g, x, y = MontMul.egcd(a, m)
        if g != 1:
            raise Exception('modular inverse does not exist')
        else:
            return x % m

    def REDC(self, T):
        N, R, logR, N_inv_neg = self.N, self.R, self.logR, self.N_inv_neg

        m = ((T&int('1'*logR, 2)) * N_inv_neg)&int('1'*logR, 2) # m = (T%R * N_inv_neg)%R        
        t = (T+m*N) >> logR # t = int((T+m*N)/R)
        if t >= N:
            return t-N
        else:
            return t

    def ModMul(self, a, b):
        if a >= self.N or b >= self.N:
            raise Exception('input integer must be smaller than the modulus N')

        R2 = self.R2
        aR = self.REDC(a*R2) # convert a to Montgomery form
        bR = self.REDC(b*R2) # convert b to Montgomery form
        T = aR*bR # standard multiplication
        abR = self.REDC(T) # Montgomery reduction
        return self.REDC(abR) # covnert abR to normal ab

if __name__ == '__main__':
    N = 123456789
    R = 2**64 # assume here we are working on 64-bit integer multiplication
    g, x, y = MontMul.egcd(N,R)
    if R<=N or g !=1: 
        raise Exception('N must be larger than R and gcd(N,R) == 1')
    inst = MontMul(R, N)

    input1, input2 = 23456789, 12345678
    mul = inst.ModMul(input1, input2)
    if mul == (input1*input2)%N:
        print ('({input1}*{input2})%{N} is {mul}'.format(input1 = input1, input2 = input2, N = N, mul = mul))

image-20230509215102946

蒙哥馬利模約簡

蒙哥馬利模約簡(REDC)是蒙哥馬利模乘最重要的部分,主要是計算 \(TR^{-1}\pmod{N} \gets REDC(T)\),算法描述如下:

圖片

一般做模約減運算\(TR^{-1} mod N\),相當於$\frac{T}{R}\pmod{N} $,需要做一次除運算,如何避免除法呢?

由於\(R=2^k\),所以\(\frac{T}{R}\)相當於T右移k位,即\(T>>k\)。但右移k位可能會抹掉T低位中的一些1,如\(7÷4=0b111>>2=0b1=1\),這個不是精確計算,而是向下取整的除法,當且僅當T是R的整數倍時,\(T/R=T>>k\)。所以實際上就是找一個\(m\),使得\(T + m N\)\(R\)的倍數,這樣計算\(\frac{T+mN}{R}\)就相當於\((T+mN) >>k\)

  • \(m\)如何找?

由於\(gcd(R,N)=1\),根據擴展歐幾里得算法得:有\(RR'-NN'=1\),且有\(1<N'<R,0<R'<N<R\)。(這裏是\(-NN'\),所以\(N'=-N^{-1}\mod{R}\)

擴展歐幾里得:

\(gcd(a,b)=1\),則必存在整數\(x,y\),使得\(ax+by=gcd(a,b)=1\)

\(\begin{gathered} \mathrm{T+mN}\equiv0{\pmod{R}} \\ \mathrm{TN'+mNN'\equiv0}\pmod{R} \\ \mathrm{TN}^{\prime}+\mathrm{m}(\mathrm{RR}^{\prime}-1)\equiv0{\pmod{R}} \\ \mathrm{TN}^{\prime}\equiv\mathrm{m}\pmod{\mathrm{R}} \end{gathered}\)

這樣就求出了\(m=TN'\pmod{R}\)

所以在已知\(a,b,N\),並計算出\(a',b',R,T\)下,蒙哥馬利約減算法\(REDC(T)=TR^{-1}\pmod{N}\)如下:

  1. 計算\(N'=-N^{-1}\pmod{R},m=TN'\pmod{R}\)
  2. 計算\(y=\frac{T+mN}{R}\),即將\(T+mN\)右移\(k\)位;
  3. \(y>N\),則\(y=y-N\),由於\(\mathrm X<\mathrm N^2,\mathrm m<\mathrm R,\mathrm N<\mathrm R\),所以\(0<y<2N\),故:\(\frac{\mathrm X+\mathrm m\mathrm N}{\mathrm R}<\frac{\mathrm N^2+\mathrm R\cdot\mathrm N}{\mathrm R}<\frac{\mathrm R\mathrm N+\mathrm R\cdot\mathrm N}{\mathrm R}=2\mathrm N\)
  4. 返回\(y=TR^{-1}\pmod{N}\)

蒙哥馬利冪模運算

蒙哥馬利冪模運算是快速計算\(a^b mod N\)的一種算法,是RSA加密算法的核心之一。

蒙哥馬利冪模的優點在於減少了取模的次數(在大數的條件下)以及簡化了除法的複雜度(在2的k次冪的進制下除法僅需要進行左移操作)。

計算方式是將冪模運算轉化爲模乘運算

例如:求D=C^15 % N

由於:ab % n = (a % n)(b % n) % n

所以令:

C = C%N

C1 =C*C % N =C^2 % N

C2 =C1*C % N =C^3 % N

C3 =C2*C2 % N =C^6 % N

C4 =C3*C % N =C^7 % N

C5 =C4*C4 % N =C^14 % N

C6 =C5*C % N =C^15 % N

即:對於E=15的冪模運算可分解爲6 個乘模運算。

歸納分析以上方法可以發現:對於任意指數E,都可採用以下算法計算 D=C^E % N

D=1

WHILE E>0

  IF E%2=0

    C=C*C % N

    E=E/2

  ELSE

    D=D*C % N

    E=E-1

RETURN D

繼續分析會發現,要知道E何時能整除 2,並不需要反覆進行減一或除二的操作,只需驗證E 的二進制各位是0還是1就可以了,從左至右或從右至左驗證都可以,從左至右會更簡潔。

D=1

FOR i=n TO 0

  D=D*D % N

  IF e=1	//e是E的最後一位【判斷E是否爲奇數】

    D=D*C % N
  
RETURN D

這樣,模冪運算就轉化成了一系列的模乘運算。

/*例如求D=C^15%N 
由於:C*k % n = (C % n)*(k % n) % n 
所以令: 
【奇數】 C1 = C*C % N =C^2 % N       1   15 
			  C2 = C1*C % N =C^3 % N      3   7 
【奇數】C3 = C2*C2 % N =C^6 % N 
				C4 = C3*C % N =C^7 % N      7   3 
【奇數】C5 = C4*C4 % N =C^14 % N 
				C6 = C5*C % N =C^15 % N     15  1 
				
蒙哥馬利冪模運算*/   
#include <iostream> 
using namespace std; 
typedef long long  __int64;
  
__int64 Montgomery(__int64 base,__int64 exp,__int64 mod)  
{  
    __int64 res = 1;  
    while(exp)  
    {  
        if ( exp&1 )  //取exp的最後一位爲1(奇數)
            res = (res*base) % mod;  
        exp >>= 1;    //exp/2
        base = (base*base) % mod;  
    }  
    return res;  
}  
int main()  
{  
    //base 底數,exponential 指數,mod 模  
    __int64 base,exp,mod;                   //base^exp % mod
    base=12,exp=15,mod=99;
    cout << base<<"^"<<exp<<"%"<<mod<<"="<<Montgomery(base,exp,mod) << endl;  
    return 0;  
}  

複雜度分析

  • 將模除運算轉換爲移位運算;

  • 當出現大量模乘運算時,可以通過並行運算進行預計算,節省時間;

參考

  1. https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
  2. 密碼學中的模乘算法——蒙哥馬利模乘(Montgomery Modular Multiplication)
  3. 蒙哥馬利約減算法
  4. 蒙哥馬利模乘
  5. 蒙哥馬利算法(Montgomery Algorithm)|蒙哥馬利約簡、模乘、模冪
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章