RSA算法

 RSA算法
作者:fnlq
【聲明】
一.本文實用於初學者,目的在於幫助大家熟悉一些系統底層的知識。
二.本文只是爲了讓廣大網友共同提高一些基礎知識,本人決無賣弄之意,只供需要這方面知識的讀者閱讀,如果你是高手,或者不需要這方面知識,請跳過。
三.本文是一篇翻譯文章,如有雷同,敬請諒解。
四.本文歡迎傳抄轉載,但是不要用於任何商業用途。請尊重作者勞動,也歡迎來信交流 [email protected]


=======================================================================

【正文】

最近大家經常在網路上討論security的問題有一個地方講起來非常頭大,就是網路竊聽的問題因爲現今大部分的資料傳遞是使用明碼,所以,有心人只要組一臺PC上網,就可以竊聽到許許多多有用的資訊,即使機器的su密碼也不能倖免所以,人們就想在資料上做加密解密的工作.在網路上所傳輸的都是經過加密之後資料,來防止第三者竊聽

  其實,對資料作加密解密的工作並不困難,只要會寫程式的人就可以想出許許多多千奇百怪的方法.但問題是,如果這個演算法一但外流了,那這個方法就破功了.所傳的碼頓時之間成爲明碼.所以,在一般公用的service,如telnet,ftp等,作者不可能使用自定的演算法作加密解密的工作.

  現今,大家最常用的方法是DES演算法DES是一個公開的演算法,但它在加密解密的過程中需要一個key.解碼時如果key不對,那還是沒效.所以,只要key不要外流,即使傳輸過程中有人竊聽,也不怕資料曝光.但DES有個問題,因爲加密解密需用同一個key,所以在傳輸時,要如何使雙方都使用同一個key?這個問題實在很頭大,因爲如果不靠其它方法,比如你自己到對方耳邊親口告訴他,或是寄一封掛號信給對方等等.單靠網路的話,這個key是無法不被第三者所知.所以,像KERBEROS這類的安全系統(它也是使用DES演算法),就必須作一些人工設定(也就是有些動作不能透過網路設定)有個演算法,RSA,可以解決上述的問題它的做法大概如下:假設資料要由A機器傳至B機器,那,由B機器用亂數決定一個key,我們稱之爲privatekey,這個key自始至終都只留在B機器裏不送出來然後,由這個privatekey計算出另一個key,我們稱之爲publickey.這個publickey的特性是幾乎不可能反演算出privatekey來然後將這個publickey透過網路丟給A機器.A機器將資料用這個publickey編碼,這個編碼過的資料一定得使用privatekey才解得開然後A機器將編碼過的資料透過網路傳給B,B再用privatekey將資料解碼這時,如果有第三者竊聽資料時,他只得到B傳給A的publickey,以及A用這個publickey編碼後的資料沒有privatekey,第三者根本無法解碼所以這個方法確實能防止第三者的竊聽
它是第一個既能用於數據加密也能用於數字簽名的算法。它易於理解和操作,也很流行。算法的名字以發明者的名字命名:Ron Rivest, Adi Shamir 和Leonard Adleman。但RSA的安全性一直未能得到理論上的證明。它經歷了各種攻擊,至今未被完全攻破。

  RSA的安全性依賴於大數分解。公鑰和私鑰都是兩個大素數( 大於 100 個十進制位)的函數。據猜測,從一個密鑰和密文推斷出明文的難度等同於分解兩個大素數的積。

  密鑰對的產生。選擇兩個大素數,p 和q 。計算:

  n = p * q

然後隨機選擇加密密鑰e,要求 e 和 ( p - 1 ) * ( q - 1 ) 互質。最後,利用 Euclid 算法計算解密密鑰d,滿足

  e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )

  其中n和d也要互質。數e和 n是公鑰,d是私鑰。兩個素數p和q不再需要,應該丟棄,不要讓任何人知道。

  加密信息 m(二進制表示)時,首先把m分成等長數據塊 m1 ,m2,..., mi ,塊長s ,其中 <= n, s 儘可能的
大。對應的密文是:

  ci = mi^e ( mod n ) ( a )

解密時作如下計算:

  mi =ci^d ( mod n ) ( b )

RSA 可用於數字簽名,方案是用 ( a ) 式簽名, ( b )式驗證。具體操作時考慮到安全性和 m信息量較大等因素,一般是先作 HASH 運算。

RSA 的安全性。 RSA的安全性依賴於大數分解,但是否等同於大數分解一直未能得到理論上的證明,因爲沒有證明破解 RSA就一定需要作大數分解。假設存在一種無須分解大數的算法,那它肯定可以修改成爲大數分解算法。目前, RSA 的一些變種算法已被證明等價於大數分解。不管怎樣,分解n是最顯然的攻擊方法。現在,人們已能分解多個十進制位的大素數。因此,模數n 必須選大一些,因具體適用情況而定。

RSA的速度。 由於進行的都是大數計算,使得RSA最快的情況也比DES慢上倍,無論是軟件還是硬件實現。速度一直是RSA的缺陷。一般來說只用於少量數據加密。

RSA的選擇密文攻擊。 RSA在選擇密文攻擊面前很脆弱。一般攻擊者是將某一信息作一下僞裝( Blind),讓擁
有私鑰的實體簽署。然後,經過計算就可得到它所想要的信息。實際上,攻擊利用的都是同一個弱點,即存在這樣一個事實:乘冪保留了輸入的乘法結構:

( XM )^d = X^d *M^d mod n

前面已經提到,這個固有的問題來自於公鑰密碼系統的最有用的特徵--每個人都能使用公鑰。但從算法上無法解決這一問題,主要措施有兩條:一條是採用好的公鑰協議,保證工作過程中實體不對其他實體任意產生的信息解密,不對自己一無所知的信息簽名;另一條是決不對陌生人送來的隨機文檔簽名,簽名時首先使用One-Way HashFunction 對文檔作HASH處理,或同時使用不同的簽名算法。在中提到了幾種不同類型的攻擊方法。   

RSA的公共模數攻擊。 若系統中共有一個模數,只是不同的人擁有不同的e和d,系統將是危險的。最普遍的情況是同一信息用不同的公鑰加密,這些公鑰共模而且互質,那末該信息無需私鑰就可得到恢復。設P爲信息明文,兩個加密密鑰爲e1和e2,公共模數是n,則:

C1 = P^e1 mod n

C2 = P^e2 mod n

密碼分析者知道n、e1、e2、C1和C2,就能得到P。

因爲e1和e2互質,故用Euclidean算法能找到r和s,滿足:

r * e1 + s * e2 = 1

假設r爲負數,需再用Euclidean算法計算C1^(-1),則

( C1^(-1) )^(-r) * C2^s = P mod n

另外,還有其它幾種利用公共模數攻擊的方法。總之,如果知道給定模數的一對e和d,一是有利於攻擊者分解模數,一是有利於攻擊者計算出其它成對的e’和d’,而無需分解模數。解決辦法只有一個,那就是不要共享模數n。

RSA的小指數攻擊。 有一種提高 RSA速度的建議是使公鑰e取較小的值,這樣會使加密變得易於實現,速度有所提高。但這樣作是不安全的,對付辦法就是e和d都取較大的值。

RSA算法是第一個能同時用於加密和數字簽名的算法,也易於理解和操作。RSA是被研究得最廣泛的公鑰算法,從提出到現在已近二十年,經歷了各種攻擊的考驗,逐漸爲人們接受,普遍認爲是目前最優秀的公鑰方案之一。RSA的安全性依賴於大數的因子分解,但並沒有從理論上證明破譯RSA的難度與大數分解難度等價。即RSA的重大缺陷是無法從理論上把握它的保密性能如何,而且密碼學界多數人士傾向於因子分解不是NPC問題。 RSA的缺點主要有:A)產生密鑰很麻煩,受到素數產生技術的限制,因而難以做到一次一密。B)分組長度太大,爲保證安全性,n 至少也要 600 bits 以上,使運算代價很高,尤其是速度較慢,較對稱密碼算法慢幾個數量級;且隨着大數分解技術的發展,這個長度還在增加,不利於數據格式的標準化。目前,SET( Secure Electronic Transaction )協議中要求CA採用比特長的密鑰,其他實體使用比特的密鑰。
首先,找出三個數,其中p,q是兩個相異的質數,r是與(p-1)(q-1)互質的數這三個數便是privatekey

接著,找出m,使得rm==1mod(p-1)(q-1)這個m一定存在,因爲r與(p-1)(q-1)互質,用輾轉相除法就可以得到了再來,計算n=pqm,n這兩個數便是publickey編碼過程是,若資料爲a,將其看成是一個大整數,假設a<n如果a>=n的話,就將a表成s進位(s<=n,通常取s=2^t),則每一位數均小於n,然後分段編碼接下來,計算b==a^mmodn,(0<=b<n),b就是編碼後的資料解碼的過程是,計算c==b^rmodpq(0<=c<pq),於是乎,解碼完畢等會會證明c和a其實是相等的

如果第三者進行竊聽時,他會得到幾個數:m,n(=pq),b他如果要解碼的話,必須想辦法得到r所以,他必須先對n作質因數分解要防止他分解,最有效的方法是找兩個非常的大質數p,q,使第三者作因數分解時發生困難

<定理>
若p,q是相異質數,rm==1mod(p-1)(q-1),a是任意一個正整數b==a^mmodpq,c==b^rmodpq,
則c==amodpq

證明的過程,會用到費馬小定理,敘述如下:
m是任一質數,n是任一整數,則n^m==nmodm 換另一句話說,如果n和m互質,則n^(m-1)==1modm)
運用一些基本的羣論的知識,就可以很容易地證出費馬小定理的 ><證明>
因爲rm==1mod(p-1)(q-1),所以rm=k(p-1)(q-1)+1,其中k是整數,因爲在modulo中是preserve乘法的x==ymodzandu==vmodz=>xu==yvmodz),
所以,c==b^r==(a^m)^r==a^(rm)==a^(k(p-1)(q-1)+1)modpq

1.如果a不是p的倍數,也不是q的倍數時,則a^(p-1)==1modp(費馬小定理)=>a^(k(p-1)(q-1))==1modp,a^(q-1)==1modq(費馬小定理)=>a^(k(p-1)(q-1))==1modq 所以p,q均能整除a^(k(p-1)(q-1))-1=>pq|a^(k(p-1)(q-1))-1,即a^(k(p-1)(q-1))==1modpq
=>c==a^(k(p-1)(q-1)+1)==amodpq

2.如果a是p的倍數,但不是q的倍數時,則a^(q-1)==1modq(費馬小定理)
=>a^(k(p-1)(q-1))==1modq=>c==a^(k(p-1)(q-1)+1)==amodq=>q|c-a
因p|a
=>c==a^(k(p-1)(q-1)+1)==0modp
=>p|c-a所以,pq|c-a=>c==amodpq

3.如果a是q的倍數,但不是p的倍數時,證明同上

4.如果a同時是p和q的倍數時,則pq|a=>c==a^(k(p-1)(q-1)+1)==0modpq>pq|c-a
=>c==amodpq
Q.E.D.


這個定理說明a經過編碼爲b再經過解碼爲c時,a==cmodn(n=pq)....
但我們在做編碼解碼時,限制0<=a<n,0<=c<n,
所以這就是說a等於c,所以這個過程確實能做到編碼解碼的功能

還有一些事值得探討的

  首先是質數的選取

上一篇提到爲了使因數分解發生困難, 所選擇的質數要愈大愈好,但這也意味著, 質數的選取也同樣的困難因爲就目前而言, 跟本沒有一個所謂的質數產生公式可用

解析數論上有一個定理, 當 p 很大時, 質數的分佈密度與 1/log p 成正比,也就是說一個質數和下一個質數的差平均而言與 log p 成正比還好 log p 的成長並不會很快, 所以就採用一個方法 --- 暴力搜尋法一個數接著一個數找 直到找到質數爲止.
即使 n 大到 2^512, 所要花的時間也不會大到天文數字,用 486 的話, 大概在數秒鐘至數十秒之內會找到 (包括判定的時間).

現在有一個問題了 如何去判定一個數是否是質數,因爲到目前爲止, 並沒有一個很有效的方法來判定,當然有人會問, 爲什麼不用試除法.嗯 如果用這個方法, 2^512 這麼大的數, 大概要除個大於 10^30 年.雖然如此, 但還是得去判斷啊

有一個方法, 是利用費馬小定理去做判定的.假設一數 p, 如果 p 是質數, a^p == a mod p,如果 p 不是質數, 那麼 a^p == a mod p 雖然也有可能成立,但成立的機率非常小, 而且 p 愈大時機率愈小。用這種方法, 我們就找一些質數來測定, 比如驗證。2^p == 2 mod p, 3^p == 3 mod p, 5^p == 5 mod p 等式是否成立,如此一來, p 是質數的機率就變得非常非常高了
現在來討論 RSA 演算法編碼解碼的速度


  因爲我們是對一些很大的數作計算,所以, 一些加減乘除的運算, 必須自己寫成函式來處理這些事就 N-digit key 的資料而言, 加減法需要 O(N) 的時間, 乘除法需要 O(N^2) 的時間至於計算 a^b mod c, 則是需要 O(N^3) 的時間, 亦即, 要對 N-digit 的資料用 N-digit key 作編碼解碼, 是需要 O(N^3) 的時間一般的實作, N 是介於 512 至 1024 之間, (太小的話很有可能被因數分解開) 所以算算 N^3, 其計算量也是相當驚人的這意味著, 用 RSA 演算法來編碼解碼其速度是非常慢的 既然 RSA 的速度很慢, 這就表示它並不適合所有情況..... 比如 ftp, 這就不適合全程使用 RSA 作編碼解碼

  如何去改善速度? 還記得之前所提到的 DES 吧? RSA 搭配上 DES 的話, 就可以彌補編碼解碼時速度太慢的問題了 先前提到用 DES 作編碼解碼時, 雙方必須使用同一個 key所以, 我們可以用 RSA 演算法將 DES key 送給對方, 而後接下來的資料, 就全部利用 DES 來做編碼解碼, 如此, 整個過程中, 因使用 RSA 而耗掉的時間就不會太多 再者, 產生 RSA key 所耗掉的時間, 也是相當驚人的先前提到, 以 N-digit key 爲例, 兩個相鄰質數平均間隔爲 O(N), 對於這些數, 我們要利用費馬小定理去判定是否可能爲質數, 而計算 a^b mod c 所花的時間爲 O(N^3), 所以算一算, 平均要找到一個 N-digit 質數, 需費時 O(N^4)所以在產生 RSA key 時也是一件非常耗時的工作所以, 一般的作法是, 先花一大把時間去找 RSA key, 往後的編碼解碼就使用這一組 key 就以 stand-alone telnet daemon 爲例好了, 可行的做法是 telnetd 一開始執行時, 先花時間運算出 RSA key, 之後 telnet 連上這個 telnetd 之後, 丟給 telnet 這個 RSA key (public), 然後 telnet 將 DES key 用這個 RSA key 編碼丟後回給 telnetd, 之後的通訊就用這個 DES key 作編碼解碼 fnlq

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章