“不給力啊,老溼!”:RSA加密與破解

“不給力啊,老溼!”:RSA加密與破解

作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!

 

加密和解密是自古就有技術了。經常看到偵探電影的橋段,勇敢又機智的主角,拿着一長串毫無意義的數字苦惱,忽然靈光一閃,翻出一本厚書,將第一個數字對應頁碼數,第二個數字對應行數,第三個數字對應那一行的某個詞。數字變成了一串非常有意義的話:

Eat the beancurd with the peanut. Taste like the ham.

主角喜極而泣……

 

這種加密方法是將原來的某種信息按照某個規律打亂。某種打亂的方式就叫做密鑰(cipher code)。發出信息的人根據密鑰來給信息加密,而接收信息的人利用相同的密鑰,來給信息解密。就好像一個帶鎖的盒子。發送信息的人將信息放到盒子裏,用鑰匙鎖上。而接受信息的人則用相同的鑰匙打開。加密和解密用的是同一個密鑰,這種加密稱爲對稱加密(symmetric encryption)。

 

如果一對一的話,那麼兩人需要交換一個密鑰。一對多的話,比如總部和多個特工的通信,依然可以使用同一套密鑰。但這種情況下,對手偷到一個密鑰的話,就知道所有交流的信息了。二戰中盟軍的情報戰成果,很多都來自於破獲這種對稱加密的密鑰。

二戰中德軍的傳奇加密機:Enigma

 

爲了更安全,總部需要給每個特工都設計一個不同的密鑰。如果是FBI這樣龐大的機構,恐怕很難維護這麼多的密鑰。在現代社會,每個人的信用卡信息都需要加密。一一設計密鑰的話,銀行怕是要跪了。

 

對稱加密的薄弱之處在於給了太多人的鑰匙。如果只給特工鎖,而總部保有鑰匙,那就容易了。特工將信息用鎖鎖到盒子裏,誰也打不開,除非到總部用唯一的一把鑰匙打開。只是這樣的話,特工每次出門都要帶上許多鎖,太容易被識破身份了。總部老大想了想,乾脆就把造鎖的技術公開了。特工,或者任何其它人,可以就地取材,按照圖紙造鎖,但無法根據圖紙造出鑰匙。鑰匙只有總部的那一把。

上面的關鍵是鎖和鑰匙工藝不同。知道了鎖,並不能知道鑰匙。這樣,銀行可以將“造鎖”的方法公佈給所有用戶。每個用戶可以用鎖來加密自己的信用卡信息。即使被別人竊聽到,也不用擔心:只有銀行纔有鑰匙呢!這樣一種加密算法叫做非對稱加密(asymmetric encryption)。非對稱加密的經典算法是RSA算法。它來自於數論與計算機計數的奇妙結合。

 

爲了瞭解RSA加密,請聽一個臥底的自白:

 

RSA加密

我是潛伏在龍鳳大酒樓的臥底。想讓下面信息以加密的方式發送到總部:

A CHEF HIDE A BED

廚子藏起來了一張牀!這是如此的重要,需要立即通知總部。千萬重要的是,不能讓反革命的廚子知道。

 

第一步是轉碼,也就是將英文轉換成某個對應的數字。這個對應很容易建立,比如:

A B C D E F G H I
1 2 3 4 5 6 7 8 9

 

將上面的信息轉碼,獲得下面的數字序列:


A CHEF HIDE A BED

1 3856 8945 1 254

這串數字完全沒有什麼祕密可言。廚子發現了這串數字之後,很容易根據數字順序,對應字母表猜出來。

 

爲了和狡猾的廚子鬥智鬥勇,我們需要對這串數字進一步加密。使用總部發給我們的鎖,兩個數字:3和10。我們分爲兩步處理。

第一步是求乘方。第一個數字是3,也就是說,總部指示我們,求上面數字串的3次方:

原字符串: 1   3   8   5   6   8   9   4   5   1   2   5   4

三次乘方: 1  27 512 125 216 512 729  64 125   1   8 125  64

第二步是求餘數。第二個上鎖的數字是10,將上面每個三次乘方除以10,獲得其餘數:

餘數: 1 7 2 5 6 2 9 4 5 1 8 5 4

 

將這串數字發回總部。中途被廚子偷看到,但一時不能瞭解其中的意思。如果還是像剛纔一樣對應字母表的話,信息是:

AGBEFBIDEAHED

這串字母完全不包含正常的單詞。

 

信息到了總部。總部開始用神奇的鑰匙來解讀。這個鑰匙是3。(偷偷告訴你的,別告訴廚子。)

(這裏鑰匙不小心和之前鎖中的一個數字相同。這只是巧合。)

解鎖過程也是兩步。第一步求鑰匙次的乘方,即3次方。第二步求它們除以10(鎖之一)的餘數。

加密信息:1   7   2   5   6   2   9   4   5   1   8   5   4

三次乘方:1 343   8 125 216   8 729  64 125   1 512 125  64 (這裏用的是鑰匙的“3”)

除十得餘:1   3   8   5   6   8   9   4   5   1   2   5   4

正是我們發送的信息。對應字母表,總部可以立即知道原來的信息。

 

特工練習

再次強調,爲了演示方便,選用了簡單的鎖和鑰匙。鎖和鑰匙只是湊巧相同。爲此,我們做一個小練習。

練習:總部新公佈出來的鎖是2987(次乘方)和3937(爲除數)。

1) 作爲特工,用上面的算法爲信息加密(你可能需要一些編程來計算,嘗試用Python的數學計算功能?)。

猜到鑰匙是什麼了呢?不是上面兩個數字中的任何一個,而是143!

2) 作爲值班人員,驗證143是鑰匙,可以解密信息。

爲了簡便,你可以只檢驗一個簡單的信息,比如“IE”。

 

下面是我根據這個練習寫的一個Python小程序。這裏的轉碼用的是ASCII編碼標準,而不是上面的A對應1,B對應2。

複製代碼
# By Vamei

#==== Agent ========
# coding covert: string to number
# By ASCII convention
def convert(original):
    return map(ord, original)

# the input is a list of integers
def encrypt(input_list):
    f = lambda x: (x**2987)%3937
    return map(f, input_list)

#==== Headquarter =====
# the input is the result of the encrypt function
def decrypt(encrypted_list):
    f = lambda x: (x**143)%3937
    return map(f, encrypted_list)

# convert numbers back to a string
def inv_convert(decrypt_list):
    f = lambda x: str(unichr(x))
    result = map(f, decrypt_list)
    return "".join(result)

# Test
message = "Go to hell!"
secret = encrypt(convert(message))
print(secret)
public = inv_convert(decrypt(secret))
print(public)
複製代碼

 

費馬與歐拉

發覺自己被愚弄了,廚子很生氣,後果很嚴重。廚子發奮看了書,知道了這個加密方法叫RSA,是三爲發明人 R. Rivest, A. Shamir和L. Adelman名字首字母合起來的。RSA算法是1977年發明的。全稱是RSA Public Key System。這個"Public Key"是公共密鑰,也就是我們上面說的鎖。再讀下去,廚子大窘。這個1977年的,現代計算機加密的RSA算法,居然源於17世紀。

 

1. 費馬小定律

RSA的原理藉助了數論中的“歐拉定理”(Euler's theorem)。17世紀的費馬首先給出一個該定理的特殊形式,即“費馬小定理”:

p是一個正的質數,a是任意一個不能被p整除的整數。那麼,ap11ap−1−1能被p整除。

 

我們並不需要太深入瞭解費馬小定理,因爲等下就會看到這個定理的“升級版”。但這個定理依然很美妙,它優美的得到乘方和整除的某種特殊關係。使用一個例子來說明它。比如p=7a=3p=7,a=3。那麼費馬小定律表示,371137−1−1可以被7整除。

事實上,上面的數字計算得到361=72836−1=728,它確實可以被7整除。

練習:嘗試一個其它的例子,比如p=5a=4p=5,a=4,驗證費馬小定律是否成立。

 

*** 數學小貼士:

1) 除 (divide),商餘數:兩個整數相除,有一個爲整數的商,和一個餘數。比如10/3=3,110/3=3,餘1。我們用一個特別的方式記錄這一敘述:

101(mod3)10≡1(mod3)

也可以寫成另一種方式:

[10]3=[1]3[10]3=[1]3

這一表述方式與“10除以3,得3餘1”這樣的方式並沒有什麼區別。但採用標準的數學方式更容易和別人交流。

 

如果我們知道:

[a]n=[b]n[a]n=[b]n

那麼存在某個整數t,且:

a=nt+ba=nt+b

 

2) 整除 (divisible):當一個整數a除以另一個整數b,餘數爲0時,那麼我們說a可以被b整除。比如說,4可以被2整除。即

[4]2=[0]2[4]2=[0]2

3) 質數 (prime number):一個質數是隻能被±1±1和這個數自身整除的整數(不包括±1±1)。比如235711132,3,5,7,11,13等等。

******

 

費馬是一名律師,也是一名業餘數學家。他對數學貢獻很大,堪稱“業餘數學家之王”。比如他和帕斯卡的通信算是概率論的開端。還有“費馬大定理”,或者稱爲“費馬猜想”。費馬有在書邊寫註釋的習慣。他在頁邊角寫下了費馬猜想,並說:

我發現了一個美妙的證明,但由於空白太小而沒有寫下來。

費馬自己的證明沒有再被發現。“費馬猜想”的證明是300多年後,以現代數學爲工具證得的,而這些數學工具在費馬的時代是不存在的。這導致現代的數學家懷疑費馬是不是在吹牛。費馬小定理是費馬的另一個定理。在費馬那裏,也還是個猜想。證明要等到歐拉。

程序員們:註釋要完整啊!

 

2. 歐拉定律

時間流過一百年。歐拉是18世紀的瑞典數學家。這位數學巨人寫了75本數學專著,幾乎把當時所有的數學領域都征服了一遍。歐拉後來被葉卡捷琳娜二世邀請到俄國。據說,無神論者狄徳羅造訪俄國,他宣稱上帝並不存在,靠雄辯擊敗了整個俄國宮廷。歐拉曾醉心神學,對上帝很虔誠。歐拉看不下去了,上前說,“先生,eiπ+1=0eiπ+1=0,所以上帝存在。請回答!” 狄徳羅敗給這個問題,灰溜溜的走了。

(這個傳說的可信度不高,因爲狄徳羅本人也是一位頗有造詣的數學家。)

 

歐拉定理(Euler's theorem)是歐拉在證明費馬小定理的過程中,發現的一個適用性更廣的定理。

 

首先定義一個函數,叫做歐拉Phi函數,即ϕ(n)ϕ(n),其中,n是一個正整數。

ϕ(n)=(1n1n)ϕ(n)=總數(從1到n−1,與n互質的整數)

比如5,那麼1,2,3,4,都與5互質。與5互質的數有4個。ϕ(5)=4ϕ(5)=4

再比如6,與1,5互質,與2,3,4並不互質。因此,ϕ(6)=2ϕ(6)=2

對於一個質數p來說,它和1, 2, 3, ..., p - 1都互質,所以ϕ(p)=p1ϕ(p)=p−1。比如ϕ(7)=6,ϕ(11)=10ϕ(7)=6,ϕ(11)=10

 

*** “互質”的數學小貼士:

1) 因子 (factor):每個整數都可以寫成質數相乘的形式,每個這樣的質數稱爲該整數的一個因子。

2) 互質 (relative prime):如果兩個整數沒有公共因子,這兩個質數互質。

******

 

歐拉定理敘述如下:

如果n是一個正整數,a是任意一個非0整數,且n和a互質。那麼,aϕ(n)1aϕ(n)−1可以被n整除。  (1)

由於質數p有ϕ(p)=p1ϕ(p)=p−1。因此,從歐拉定理可以推出費馬小定理。我們可以只使用歐拉定理,把費馬小定理拋到腦後了。我們用一個例子簡單的檢驗歐拉定理。如果n是6,那麼ϕ(6)=2ϕ(6)=2。讓a是11,和6互質。1121112−1爲120,確實可以被n,也就是6整除,符合歐拉定理。

 

數學中還有一個關於Phi函數的推論

m和n是互質的正整數。那麼,ϕ(mn)=ϕ(m)ϕ(n)ϕ(mn)=ϕ(m)ϕ(n)        (2)

 

 

RSA西遊記

下面我們要進入實質的證明。除了上面的(1)和(2)推論,還需要提前說明一個問題,即:

[ab]n=[a]n[b]n[ab]n=[a]n[b]n        (3)

證明:假設a和b除以n的餘數爲c1,c2c1,c2。a和b可以寫成a=nt1+c1,b=nt2+c2a=nt1+c1,b=nt2+c2。那麼,ab=n2t1t2+nt1c2+nt2c1+c1c2ab=n2t1t2+nt1c2+nt2c1+c1c2。因此ab除以n的餘數爲c1c2c1c2。即[ab]n=[a]n[b]n[ab]n=[a]n[b]n

根據此可以推論,[am]n=[a]mn[am]n=[a]nm

 

演一出叫做“西遊記”的大戲,選角開始:

先選擇兩個質數p和q,分別是沙和尚和白龍馬。讓n=pqn=pq,n是唐僧。一路向西,唐僧靠的是沙和尚和白龍馬出力:一個背行李,一個馱人。

k=ϕ(n)=(p1)(q1)k=ϕ(n)=(p−1)(q−1)。這裏使用了(2)以及“質數p的Phi函數值爲p-1”。k是八戒,也就是Phi(唐僧),就是唐僧的一個跟屁蟲。

選擇任意d,並保證它與k互質。d是觀音。觀音姐姐在高老莊,真的是把八戒給“質”了一把。

取整數e,使得[de]k=[1]k[de]k=[1]k。也就是說de=kt+1de=kt+1,t爲某一整數。e是悟空,橫行無忌。

 

我們記得公開的用來上鎖的兩個數字,它們分別是悟空e和唐僧n。悟空威力大,負責乘方。唐僧太嘮叨:一切妖怪見到它,就變成了餘數。悟空和唐僧合作,就把世界搞亂了。

總部的觀音姐姐d看不下去了。觀音姐姐威力也大,也是乘方。再逼着唐僧重新嘮叨。世界就恢復了。

善哉,善哉!

 

 

我們看一下這一魔幻大片“西遊記”的現實主義原理。根據歐拉定理(1),對於任意z,如果z與n互質,那麼:

[zϕ(n)]n=[zk]n=[1]n[zϕ(n)]n=[zk]n=[1]n

因此,

[zde]n=[zkt+1]n=[(zk)tz]n=[z]n[zde]n=[zkt+1]n=[(zk)tz]n=[z]n

上面主要使用了de=kt+1de=kt+1以及(3)。也就是說:

[zde]n=[z]n[zde]n=[z]n

根據(3)的推論,有

([ze]n)d=[z]n([ze]n)d=[z]n

妖怪z,經過e和d的各一道,又變回了妖!上面過程中,悟空e和觀音d忙得不亦樂乎,唐僧n就在一旁邊嘮叨邊打醬油了。

這一等式,也正是我們加密又解密的過程 (加密: 悟空次方 + 唐僧嘮叨。解密: 觀音次方 + 唐僧嘮叨)。悟空和唐僧是公鑰,扔出去亮相。觀音是私鑰,偷偷藏起來,必要的時候纔出來。

(上面都默認餘數是最小正餘數,也就是說,10除以3的餘數爲1,而不是4。儘管4也可以算是10的餘數,即[4]3=[10]3[4]3=[10]3。)

姐姐,饒了我吧。

 

3和8兩個妖怪見到唐僧5,都被嘮叨成了餘數3。這樣就觀音姐姐就算法力無邊,還是沒法還原。爲了讓唐僧求餘的時候,不會把數字弄混了,RSA算法要求所有妖怪z小於唐僧n。爲了對足夠多的字符轉碼加密,n必須大過最大的妖怪。

但唐僧n大更重要的原因是要保護馬仔。想破解,必須找到觀音。回顧我們選擇角色的過程。我們可以這樣破解:唐僧n是公開的,1) 先找到它的隱藏手下沙和尚和白龍馬。2) 沙和尚和白龍馬知道了,那麼二師兄k就保不住了。3) de = kt + 1,即找到一個e,可以讓de - 1被k整除。觀音姐姐就找到了。

上面的整個破解過程中,最困難的是第一步,即找到兩個隱藏的打手。通常,p和q都會選的非常大,比如說200位。這導致唐僧n也非常大,有400位。尋找一個400位數字的質數分解並不容易,我們要做的除法運算次數大約爲10400/210400/2。這是1019910199次除法運算!天河2號每秒浮點運算是10161016級別。那麼,找到隱藏打手的工作,大約需要1017410174年……。這個活,看來只能佛祖幹了。

 

練習 如果唐僧不夠大的話,馬仔就危險了。想想之前的廚子,知道悟空是3,唐僧是10。隱藏打手是誰? 八戒呢? 觀音呢?

 

總之,帶頭大哥不夠“罩”的話,團伙就要被一窩端了。

 

 

總結

正如我在“數學與編程”中提到的,數學可以是程序員軍火庫中有力的武器。加密、解密這一事關IT安全的大課題,卻和數論這一純粹數學學科發生奇妙的關係。RSA算法的數學基礎在於歐拉定理。這一誕生了幾百年沒有什麼實用性的數學理論,卻在網絡時代,找到自己的棲身之處。

RSA算法是非對稱算法。公開的加密方式,私有的解密方式。RSA安全的關鍵在於很難對一個大的整數進行因子分解。下一次,如果看到RSA被破解之類的消息,臥底必須大喊一聲:“不給力呀,老溼!”

 

這篇文章已經充分的準備了數學,但(1), (2), (3)還可以深挖下去。如果這篇文章收穫夠多“贊”,就準備寫一個續篇。討論一下歐拉定理的證明,以及一些特殊情況下的RSA破解。

 

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