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

發表於2015-12-24

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

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

將上面的資訊轉碼,獲得下面的數字序列:

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

為了和狡猾的廚子鬥智鬥勇,我們需要對這串數字進一步加密。使用總部發給我們的鎖,兩個數字: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。

費馬與尤拉

發覺自己被愚弄了,廚子很生氣,後果很嚴重。廚子發奮看了書,知道了這個加密方法叫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整除的整數。那麼,\(a^{p-1} 1\)能被p整除。

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

事實上,上面的數字計算得到\(3^6 1 = 728\),它確實可以被7整除。

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

*** 數學小貼士:

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

\(10 equiv 1 (mod, 3)\)

也可以寫成另一種方式:

\([10]_3 = [1]_3\)

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

如果我們知道:

\([a]_n = [b]_n\)

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

\(a = nt + b\)

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

\([4]_2 = [0]_2\)

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

******

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

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

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

程式設計師們:註釋要完整啊!

2. 尤拉定律

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

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

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

首先定義一個函式,叫做尤拉Phi函式,即\(phi(n)\),其中,n是一個正整數。

\(phi(n)\) = 總數(從1到n-1,與n互質的整數)

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

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

對於一個質數p來說,它和1, 2, 3, …, p – 1都互質,所以\(phi(p) = p 1\)。比如\(phi(7) = 6, phi(11) = 10\)

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

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

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

******

尤拉定理敘述如下:

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

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

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

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

RSA西遊記

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

\([ab]_n = [a]_n[b]_n\)        (3)

證明:假設a和b除以n的餘數為\(c_1, c_2\)。a和b可以寫成\(a = nt_1 + c_1, b = nt_2 + c_2\)。那麼,\(ab = n^2t_1t_2 + nt_1c_2 + nt_2c_1 + c_1c_2\)。因此ab除以n的餘數為\(c_1c_2\)。即\([ab]_n = [a]_n[b]_n\)

根據此可以推論,\([a^m]_n = [a]_n^m\)

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

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

\(k = phi(n) = (p 1)(q 1)\)。這裡使用了(2)以及“質數p的Phi函式值為p-1”。k是八戒,也就是Phi(唐僧),就是唐僧的一個跟屁蟲。

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

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

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

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

善哉,善哉!

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

\([z^{phi(n)}]_n = [z^k]_n = [1]_n\)

因此,

\([z^{de}]_n = [z^{kt + 1}]_n = [(z^k)^tz]_n = [z]_n\)

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

\([z^{de}]_n = [z]_n\)

根據(3)的推論,有

\(([z^e]_n)^d = [z]_n\)

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

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

(上面都預設餘數是最小正餘數,也就是說,10除以3的餘數為1,而不是4。儘管4也可以算是10的餘數,即\([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位數字的質數分解並不容易,我們要做的除法運算次數大約為\(sqrt{10^{400}}/2\)。這是\(10^{199}\)次除法運算!天河2號每秒浮點運算是\(10^{16}\)級別。那麼,找到隱藏打手的工作,大約需要\(10^{174}\)年……。這個活,看來只能佛祖幹了。

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

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

總結

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

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

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

相關文章