RSA算法是由MIT的Ron Rivest,Adi Shamir和Len Adleman於1977年提出並於1978年發表的算法。自其誕生之日起,該算法就成爲被普遍接受並實現的通用公鑰加密方法。算法
算法描述安全
RSA算法使用乘方模運算,明文以分組爲單位進行加密,每一個分組的二進制值均小於模n(爲兩個大素數的乘積),在實際應用中,分組的大小是i位,其中2i < n ≤ 2i+1函數
對明文分組M和密文分組C,加密和解密過程以下:性能
C = Me mod n 測試
M = Cd mod n = Med mod n加密
公鑰爲PU = {e , n} 私鑰位PR = {d , n}spa
該算法用到下列元素:對象
兩個素數p,q (保密的,選定的)blog
n = pq (公開的,計算得出的)數學
e知足gcd(φ(n) , e) = 1; 1 < e < φ(n) (公開的,選定的)
d ≡ e-1 (mod φ(n)) (保密的,計算得出的)
當e和d互爲模φ(n)的乘法逆時,Med mod n = M (當e與φ(n)互素時必有乘法逆)
證實: ed mod φ(n) = 1 等效於 ed = kφ(n) + 1 k∈Z
Mkφ(n) + 1 mod n = Mk(p - 1)(q - 1) + 1 mod n n = p × q
首先可證實 Mk(p - 1)(q - 1 ) + 1 mod p = M mod p
若M與p不互素,因爲p是素數,則p必可整除M,此時M mod p = 0
Mk(p - 1)(q - 1) + 1 mod p = 0 = M mod p
若M與p互素,由歐拉定理,Mφ(p) mod p = 1
Mk(p - 1)(q - 1) + 1 mod p = [(M)Mk(p - 1)(q - 1) ] mod p
= [(M)(M(p - 1))k(q - 1) ] mod p
= [(M)(Mφ(p))k(q - 1) ] mod p
= (M mod p) × [(Mφ(p)) mod p]k(q - 1)
= M mod p
[Mk(p - 1)(q - 1) + 1 - M] mod p = [Mk(p - 1)(q - 1) + 1 mod p] - [M mod p] = 0
所以p整除[Mk(p - 1)(q - 1) + 1 - M] ,同理q也整除[Mk(p - 1)(q - 1) + 1 - M]。由於p和q是不一樣的素數,因此一定存在一個整數r知足:
[Mk(p - 1)(q - 1) + 1 - M] = px1 = qx2 = pqr = nr
故n整除[Mk(p - 1)(q - 1) + 1 - M],因此Mkφ(n) + 1 mod n = Mk(p - 1)(q - 1) + 1 mod n = M
RSA的加密、解密過程及實例
在這個例子中,明文是一串字母,每一個字母與一個兩位的十進制數字對應(如a=00,A=26),明文的每一分組塊由四個十進制數字組成,即兩個字母。
計算上的簡化
一、模算術裏的求冪運算
經過兩個技巧進行計算上的簡化,
1.應用模算術的如下性質來計算模冪運算,以免先求冪再求模帶來中間值過大的問題
[(a mod n) × (b mod n)] mod n = (a × b) mod n
2.由於RSA中所用指數很大,因此還應考慮冪運算的效率問題。如x16,若直接計算須要15次乘法,若是重複計算每一箇中間結果的平方,獲得x2,x4,x8,x16,那麼只須要4次乘法。同理,計算x11 mod n,能夠先計算 x mod n,x2 mod n,x4 mod n,x8 mod n,再計算[(x mod n) × (x2 mod n) × (x8 mod n)] mod n
更通常地,假定咱們要計算ab,其中a,b∈正整數。若將b表示成二進制數bkbk-1···b0,則更加方便提升冪運算的效率。
二、用公鑰進行有效運算
爲了加快RSA算法在使用公鑰是的運算速度,一般會選擇一個特定的e,大多數狀況下選爲65537(216+1),其它兩個經常使用的選擇是3和17。之因此選這些數,是由於這些數裏都只有兩個有效位(65537 = 1000 0000 0000 0001b, 3 = 11, 17 = 1 0001),因此在求冪運算時須要的乘法次數極小化了。
若是指數過小,如e = 3,RSA甚至會遭受一些簡單的攻擊,假設有三個不一樣的RSA用戶,他們都使用指數e = 3,可是他們的模數n各不相同,即n1,n2,n3。現有一用戶A以加密方式給他們三個發送相同的消息M,則三個密文爲:C1 = M3 mod n1,C2 = M3 mod n2,C3 = M3 mod n3。頗有可能n1,n2,n3是兩兩互素的,因此運用中國剩餘定理能夠計算出M3 mod (n1n2n3)。根據RSA規則,M應該比模數ni小,因此有M3 < n1n2n3,從而攻擊者只要計算M3就能夠了。解決辦法是給每個待加密的消息分組M填充一個惟一的僞隨機位串能夠阻止這種攻擊。
此外,因爲選定了e,爲了確保e和φ(n)互素,由於e = 65537 是素數,p,q是大素數,故所選p,q須要知足如下式子
[(p-1)×(q-1)] mod e ≠ 0
[(p-1) mod e × (q-1) mod e] mod e ≠ 0
(p-1) mod e ≠ 0 且 (q-1) mod e ≠ 0
三、用私鑰進行有效運算
因爲d不像e同樣是選定的爲簡化計算的值,爲了加快冪運算,能夠運用中國剩餘定理。先定義一些中間值:
Vp = Cd mod p Vq = Cd mod q
應用CRT的公式有:
Xp = q × (q-1 mod p) Xq = p × (p-1 mod q)
M = (VpXp + VqXq) mod n
進一步用費馬定理簡化Vp,Vq的計算,即若是p和a互素,則ap-1 ≡ 1 (mod p),則
Vp = Cd mod p = Ck(p-1)+d mod (p-1) mod p = Ck(p-1) mod p × Cd mod (p-1) mod p
= Cd mod (p-1) mod p
同理 Vq = Cd mod q = Cd mod (q-1) mod q
其中d mod (p-1),d mod (q-1),Xp,Xq(求乘法逆元素可用擴展Euclid算法計算)均可預先計算出來,和直接計算M = Cd mod n相比,上述的計算速度大約快4倍。
四、密鑰產生
在應用公鑰密碼進行通訊以前,通訊各方都必須產生一對密鑰,即
1.肯定兩個素數p和q
2.選擇e,並計算d
首先爲避免窮舉攻擊,p和q必須是大素數,此外要選擇有效的算法來產生這樣的大素數。目前並無有效的方法產生任意大素數,所以一般的方法是隨機挑選一個指望大小的奇數,而後測試它是不是素數,若不是則挑選下一個隨機數直至檢測到素數爲止。這裏用到的各類素性測試方法幾乎都是機率測試方法,須要執行屢次才能儘量逼近100%。
由數論中的素數定理可知,在N附近平均每隔lnN個整數就有一個素數,這樣在找到一個素數以前,平均要測試大約lnN個整數。因爲每隔偶數會被當即拒絕,故實際只須要測試lnN/2個整數。
若先肯定e,則須要進一步篩選知足(p-1) mod e ≠ 0 (q-1) mod e ≠ 0 的p和q。
若後肯定e,則需選擇知足gcd(φ(n) , e) = 1 的e
最後應用擴展Euclid算法計算 d ≡ e-1 (mod φ(n))
RSA的安全性
對RSA算法的攻擊可能有以下4種方式:
窮舉攻擊:試圖窮舉全部可能的密鑰
數學攻擊:實質是試圖分解兩個素數的乘積
計時攻擊:依賴於解密算法的運行時間
選擇密文攻擊:利用了RSA算法的性質
數學攻擊
用數學攻擊RSA的途徑有如下三種:
一、分解n爲兩個素因子,從而計算出φ(n) = (p-1)(q-1),進而肯定d ≡ e-1 (mod φ(n))
二、直接肯定φ(n)而不去肯定p和q,這樣也能計算出d ≡ e-1 (mod φ(n))
三、直接肯定d,而不肯定φ(n)
對RSA的密碼分析的討論大都集中在第一種攻擊方式,即因子分解n。如今已知從e和n肯定d的算法至少和因子分解n同樣費時,所以,咱們能夠將因子分解的性能做爲基準來評價RSA的安全性。隨着計算能力的不斷加強,目前密鑰大小取1024到2048位是合適的。此外p和q最好還知足如下限制條件:
一、p和q的長度應僅相差幾位,對1024位(309個十進制位)的密鑰而言,p和q都應約在1075到10100之間。
二、(p-1)和(q-1)都應有一個大的素因子。
三、gcd(p-1,q-1)應該較小
另外已證實,若e<n且d<n1/4,則d很容易被肯定
計時攻擊
攻擊者能夠經過記錄計算機解密消息所用的時間來肯定私鑰。因爲模乘函數的執行時間只在幾種情形中其執行時間比整個模冪運算的平均執行時間要長得多,但在大多數情形下其執行速度至關快,計時攻擊從最左位bk開始,一位一位地執行,攻擊者根據每次執行時間的長度來推算。
解決辦法:
一、不變的冪運算時間:保證全部冪運算在返回結果前執行的時間都相同。這種方法雖然簡單,但會下降算法的性能。
二、隨機延時:經過在求冪算法中加入隨機延時來迷惑攻擊者
三、隱蔽:執行冪運算以前先將密文乘上一個隨機數,使得攻擊者不知道計算機正在處理的是密文的哪些位,以防止攻擊者一位一位地進行分析嗎,而這種分析正是計時攻擊的本質所在。
RSA數據安全公司在它們產品中就使用了隱蔽方法,其具體實現以下
一、產生0只n-1之間的祕密的隨機數r
二、計算C’ = Cre mod n
三、計算M’ = (C’)d mod n
四、計算M = M’r-1 mod n 其中r-1是r的模n的乘法逆元。根據red mod n = r mod n可證實結論是正確的,據RSA公司聲稱應用了該隱蔽方法,運算性能下降了2%-10%
選擇密文攻擊
基本的RSA算法易受選擇密文攻擊(CCA)。攻擊者能夠選擇一個明文,運用目標對象的公鑰加密,而後再經過某些手段得到目標對象用私鑰對密文解密後的明文。看起來好像沒什麼用處,實則否則,攻擊者其實是將需破解的密文作了一番數學包裝後,再發給攻擊目標,因爲解密後的明文咋看起來不是重要機密,所以就較容易被截獲或者盜取。
利用CCA攻擊RSA利用了RSA以下的性質
E(PU , M1) × E(PU , M2) = E(PU , [M1 × M2])
進而用以下方式解密C = Me mod n
一、計算 X = (C × 2e) mod n = (Me mod n) × (2e mod n) = (2M)e mod n
二、將X做爲選擇明文提交,並收到Y = Xd mod n = (2M)ed mod n = 2M
爲了防止這種簡單攻擊,實用的基於RSA的密碼體制在加密以前都會對明文進行隨機填充。不過簡單的隨機填充已被證實不足以提升指望的安全性,所以RSA公司推薦了一種稱爲最優非對稱加密填充(OAEP)的程序對明文進行修改。
一、首先將加密參數P經過Hash函數處理並輸出到總體數據塊DB一側,明文的值也總體複製到DB的另外一側,DB剩餘部分用0進行填充。
二、而後隨機選擇一個種子,使用一種叫作掩碼生成函數MGF,輸出的Hash值和DB異或產生maskedDB。
三、該maskedDB一樣經過MGF函數,輸出Hash值與種子進行異或產生MaskedSeed
四、最後MaskedSeed和maskedDB共同組成EM做爲最終的填充結果。
加密公式 DB = H(P) || Padding || M
maskedDB = DB⊕MGF(Seed)
maskedSeed = Seed⊕MGF(maskedDB)
EM = maskedSeed || maskedDB
解密公式 Seed = maskedSeed⊕MGF(maskedDB)
DB = maskedDB⊕MGF(Seed)