RSA簡介(二)——模冪算法


  版權申明:本文為博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須注明原文網址

  http://www.cnblogs.com/Colin-Cai/p/7290010.html 

  作者:窗戶

  QQ:6679072

  E-mail:6679072@qq.com

  RSA最終加密、解密都要用到模乘的冪運算,簡稱模冪運算。

  回憶一下RSA,從明文A到密文B

  B=Ae1%N

  對B解密回到明文A,就是

  A=Be2%N

  其中,一般來說,加密公鑰中的e1一般會比較小,取65537居多,但解密的時候,這個e2是一個非常非常大的數,顯然,直接通過e2次模乘來解密是不現實的。

  為了讓RSA的加密、解密成為現實,我們必須要找一個好的算法來做模冪運算。

 

  借上一節我設定的符號,以區別於傳統上的冪的數學表示,

  定義a#b為a和b的模乘,

  定義a##n為n個a的模乘,或稱a的n階模乘。

 

  a = a##1,

  a##2 = a#a,

  a##4 = (a##2) # (a##2),

  ...

  a##2n = (a##2n-1) # (a##2n-1),

  從而,進行了n次模乘,分別獲得了1、21 、22 ...2n 個a的模乘結果,

  而1、21 、22 ...2n 取其中任意一部分的和可以覆蓋1~2n-1的所有整數。

 

  從而我們得到了一個算法來計算a##b:

  先不斷通過每次得到的新結果自己同自己模乘,得到

  a、a##2、a##4...a##2n,使得滿足2n≤b<2n+1

  再將b化為二進制表示,實際上也就是表示為2的各次冪相加形式,

  然后找到對應每個2的冪次a模乘結果,

  然后再把這些結果依次模乘,得到最終結果。

  打個比方,如果想求a##21,

  21用二進制表示為10101,所以21 = 16+4+1,

  第一步,求得a##2,a##4,a##8,a##16,

  第二步,取a,a##4,a##16,三者模乘就是最終需要的結果。

  

  當然,可以把第一步求a的2n階模乘和第二步取需要的模乘融合在一起,這樣就不需要存儲每一個a的2n階模乘結果,從而存儲空間可以為常數級,而之前存儲空間為線性級。

  該算法用bc描述如下:

  

#!/usr/bin/bc -q
define mod_mul(a1,a2,n)// a1*a2%n
{
        return a1*a2%n;
}
define mod_exp(a,b,n)// a^b%n {
while(b%2==0) { a = mod_mul(a,a,n); b /= 2; } ret = a; b /= 2; while(b!=0) { a = mod_mul(a,a,n); if(b%2 == 1) ret = mod_mul(a,ret,n); b /= 2; } return ret; } a=read(); b=read(); n=read(); print mod_exp(a,b,n),"\n" quit

 

  該算法求a##b所做模乘次數:

  求各個a的2n階模乘,所做模乘次數為log2b取整,也就是b的二進制的位數減1;

  取相應的2的正整數次冪的模乘結果再做模乘,所做模乘次數為b的二進制中1的個數減1。

  兩者加一起為模乘次數。

  比如上面想求a##21,21用二進制表示為10101,所以該算法所需要模乘次數為(5-1)+(3-1)=6次。

  

  但此算法未必是最優的,我們來看看如下例子:

  想求a##441,

  441用二進制展開為110111001,於是模乘次數應該是(9-1)+(6-1)=13次。

  但我們可以用另外一種方式來求a##441,

  441 = 21 * 21,

  a##441 = (a##21) ## 21,

  我們求b = a##21需要6次模乘,

  再求b##21需要6次模乘,總共只需要12次模乘,比剛才少了1次。

  

  441是合數,我們再取個質數,239。

  239寫成二進制是11101111,那么根據我們的算法應該做的模乘次數為(8-1)+(7-1)=13次。

  239 = 14*17+1,

  a##239 = ((a##14) ## 17) # a,

  先求b = a##14,需要5次模乘,

  再求c = b##1,需要5次模乘,

  最后再與a模乘,需要1次模乘,

  總共11次模乘,比13次要少。

 

  但是,即便是合數分解了,也未必得到更好的結果。

  例如49 = 7*7,

  分解前,49表示為二進制為110001,要做(6-1)+(3-1)=7次模乘,

  可是分解后,7表示為二進制制為111,

  總共要做(3-1)+(3-1)+(3-1)+(3-1)=8次模乘了。

 

  從而我們可以知道,我們給出的算法雖然是一個線性時間算法,但未必是最優算法,不過做到線性時間算法,從運算時間復雜度上來說,的確沒有時間復雜度是這個算法的低階無窮大級的算法了,從這個意義上,此算法已經“最優”了。

  如何做到最少次模乘?

  本問題為以下問題:

  (1)集合A初始為{1}

  (2)每一步從集合A中取兩個數a和b,ab可相同,讓c = a+b,再把c並入集合A,

    A = A∪{c}

  (3)輸入正整數e,求A里面有元素e的最小步驟的過程。

  

  可惜此問題獲得最優解似乎沒有很好的算法,甚至遠高於RSA可能基於的安全性——大數分解,但存在相對好的算法,從而可以用來改進我們的模冪算法。

  

  模冪算法是RSA的核心,不僅僅加密解密的時候需要,尋找密鑰的時候也是需要的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM