密碼學是在編碼與破譯的斗爭實踐中逐步發展起來的,并隨著先進科學技術的應用,已成為一門綜合性的尖端技術科學。
密碼學發展史
在說RSA加密算法之前, 先說下密碼學的發展史。其實密碼學的誕生,就是為了運用在戰場,在公元前,戰爭之中出現了秘密書信。在中國歷史上最早的加密算法的記載出自于周朝兵書《六韜.龍韜》中的《陰符》和《陰書》。在遙遠的西方,在希羅多德(Herodotus)的《歷史》中記載了公元前五世紀,希臘城邦和波斯帝國的戰爭中,廣泛使用了移位法進行加密處理戰爭通訊信息。
相傳凱撒大帝為了防止敵人竊取信息,就使用加密的方式傳遞信息。那么當時的加密方式非常的簡單,就是對二十幾個羅馬字母建立一張對照表,將明文對應成為密文。那么這種方式其實持續了很久。甚至在二戰時期,日本的電報加密就是采用的這種原始加密方式。
早期的密碼學一直沒有什么改進,幾乎都是根據經驗慢慢發展的。直到20世紀中葉,由香農發表的《秘密體制的通信理論》一文,標志著加密算法的重心轉移往應用數學上的轉移。于是,逐漸衍生出了當今重要的三類加密算法:非對稱加密、對稱加密以及哈希算法(HASH嚴格說不是加密算法,但由于其不可逆性,已成為加密算法中的一個重要構成部分)。
1976年以前,所有的加密方法都是同一種模式:加密和解密使用同樣規則(簡稱"密鑰"),這被稱為"對稱加密算法",使用相同的密鑰,兩次連續的對等加密運算后會恢復原始文字,也有很大的安全隱患。
1976年,兩位美國計算機學家Whitfield Diffie 和 Martin Hellman,提出了一種嶄新構思,可以在不直接傳遞密鑰的情況下,完成解密。這被稱為"Diffie-Hellman密鑰交換算法"。也正是因為這個算法的產生,人類終于可以實現非對稱加密了:A給B發送信息
- B要先生成兩把密鑰(公鑰和私鑰)。公鑰是公開的,任何人都可以獲得,私鑰則是保密的。
- A獲取B的公鑰,然后用它對信息加密。
- B得到加密后的信息,用私鑰解密。
理論上如果公鑰加密的信息只有私鑰解得開,那么只要私鑰不泄漏,通信就是安全的。
1977年,三位數學家Rivest、Shamir 和 Adleman 設計了一種算法,可以實現非對稱加密。這種算法用他們三個人的名字命名,叫做RSA算法。從那時直到現在,RSA算法一直是最廣為使用的"非對稱加密算法"。毫不夸張地說,只要有計算機網絡的地方,就有RSA算法。這種算法非常可靠,密鑰越長,它就越難破解。根據已經披露的文獻,目前被破解的最長RSA密鑰是232個十進制位,也就是768個二進制位,因此可以認為,1024位的RSA密鑰基本安全,2048位的密鑰極其安全,當然量子計算機除外。
RSA算法的原理
下面進入正題,解釋RSA算法的原理,其實RSA算法并不難,只需要一點數論知識就可以理解。
歐拉函數
任意給定正整數n,請問在小于等于n的正整數之中,有多少個與n構成互質關系?(比如,在1到8之中,有多少個數與8構成互質關系?)計算這個值的方法就叫做歐拉函數,以φ(n)表示。
- 計算8的歐拉函數,和8互質的 1、2、3、4、5、6、7、8
φ(8) = 4
如果n是質數的某一個次方,即 n = p^k (p為質數,k為大于等于1的整數),則φ(n) = φ(p^k) = p^k - p^(k-1)。也就是φ(8) = φ(2^3) =2^3 - 2^2 = 8 -4 = 4 - 計算7的歐拉函數,和7互質的 1、2、3、4、5、6、7
φ(7) = 6
如果n是質數,則 φ(n)=n-1 。因為質數與小于它的每一個數,都構成互質關系。比如5與1、2、3、4都構成互質關系。 - 計算56的歐拉函數
φ(56) = φ(8) * φ(7) = 4 * 6 = 24
如果n可以分解成兩個互質的整數之積,即 n = p * k ,則φ(n) = φ(p * k) = φ(p1)*φ(p2)
歐拉定理:如果兩個正整數m和n互質,那么m的φ(n)次方減去1,可以被n整除。
歐拉定理.png
費馬小定理:歐拉定理的特殊情況,如果兩個正整數m和n互質,而且n為質數!那么φ(n)結果就是n-1。
費馬小定理.png
模反元素
還剩下最后一個概念,模反元素:如果兩個正整數e和x互質,那么一定可以找到整數d,使得 ed-1 被x整除,或者說ed被x除的余數是1。
那么d就是e相對于x的模反元素。
等式轉換
-
根據歐拉定理
等式轉換1 -
由于1^k ≡ 1,等號左右兩邊都來個k次方
等式轉換 -
由于1* m ≡ m,等號左右兩邊都乘上m
等式轉換3.png
根據模反元素,因為e*d 一定是x的倍數加1。所以如下:
通過多次的等式轉換。終于可以將這兩個等式進行合并了!如下:
這個等式成立有一個前提!就是關于模反元素的,就是當整數e和φ(n)互質!一定有一個整數d是e相對于φ(n)的模反元素。
我們可以測試一下。
m取值為4
n取值為15
φ(n)取值為8
e 如果取值為3
d 可以為 11、19...(模反元素很明顯不止一個,其實就是解二元一次方程)
如果你測試了,那么你可以改變m的值試一下,其實這個等式不需要m和n 互質。只要m小于n 等式依然成立。
這里需要注意的是,我們可以看做 m 通過一系列運算得到結果仍然是 m。這一系列運算中,分別出現了多個參數n、φ(n)、e還有d。
m 的 e乘上d 次方為加密運算,得到結果 c
c 模以 n 為解密運算,得到結果 m
這似乎可以用于加密和解密。但這樣,加密的結果會非常大。明文數據將非常小(雖然RSA用于加密的數據也很小,但是沒這么大懸殊),真正的RSA要更加強大,那么RSA是怎么演變來的呢??
早期很多數學家也停留在了這一步!直到1967年迪菲赫爾曼密鑰交換打破了僵局!
迪菲赫爾曼密鑰交換
這個密鑰交換當時轟動了整個數學界!而且對人類密碼學的發展非常重要,因為這個偉大的算法能夠拆分剛才的等式。當非對稱加密算法沒有出現以前,人類都是用的對稱加密。所以密鑰的傳遞,就必須要非常小心。
迪菲赫爾曼密鑰交換 就是解決了密鑰傳遞的保密性,我們來看一下
假設一個傳遞密鑰的場景。算法就是用3 的次方去模以17。 三個角色
- 服務器 隨機數 15
這個15只有服務器才知道。通過算法得到結果 6 因為 3的15次方 mod 17 = 6 。然后將結果 6 公開發送出去,拿到客戶端的 12 ,然后用12^15 mod 17 得到結果10(10就是交換得到的密鑰) - 客戶端 隨機數13
客戶端用3 的 13次方 mod 17 = 12 然后將得到的結果12公布出去。
拿到服務器的 6 ,然后用6^13 mod 17 得到結果10(10就是交換得到的密鑰) - 第三者
第三者只能拿到6 和 12 ,因為沒有私密數據13、15,所以它沒法得到結果10。
為什么 6的13次方會和12的15次方得到一樣的結果呢?因為這就是規律,我們可以用小一點的數字測試一下3^3 mod 17 = 10和10 ^ 2 mod 17 ; 3 ^ 2 mod 17 = 9和9^3 mod 17結果都是15。迪菲赫爾曼密鑰交換最核心的地方就在于這個規律
RSA的誕生
現在我們知道了m^e % n = c是加密,c^d % n = m是解密,m就是原始數據,c是密文,公鑰是n和e,私鑰是n和d,所以只有n和e是公開的。加密時我們也要知道φ(n)的值,最簡單的方式是用兩個質數之積得到,別人想破解RSA也要知道φ(n)的值,只能對n進行因數分解,那么我們不想m被破解,n的值就要非常大,就是我們之前說的,長度一般為1024個二進制位,這樣就很安全了。但是據說量子計算機(用于科研,尚未普及)可以破解,理論上量子計算機的運行速度無窮快,大家可以了解一下。
以上就是RSA的數學原理
檢驗RSA加密算法
我們用終端命令演示下這個加密、解密過程。
假設m = 12(隨便取值,只要比n小就OK),n = 15(還是隨機取一個值),φ(n) = 8,e = 3(只要和φ(n)互質就可以),d = 19(3d - 1 = 8,d也可以為3,11等等,也就是d = (8k + 1)/3 )
終端分別以m=12,7輸入結果
OpenSSL進行RSA的命令運行
Mac可以直接使用OpenSSL,首先進入相應文件夾
- 生成公私鑰
// 生成RSA私鑰,文件名為private.pem,長度為1024bit
openssl genrsa -out private.pem 1024
// 從私鑰中提取公鑰
openssl rsa -in private.pem -pubout -out publick.pem
// 查看剛剛生成好的私鑰
cat private.pem
// 查看剛剛生成好的公鑰
cat publick.pem
我們可以看到base64編碼,明顯私鑰二進制很大,公鑰就小了很多。
這時候我們的文件夾內已經多了剛剛生成好的公私鑰文件了
// 將私鑰轉換為明文
openssl rsa -in private.pem -text -out private.txt
里面就是P1、P2還有KEY等信息。
- 對文件進行加密、解密
// 編輯文件message內容為hello Vincent!!!
// 剛剛的public.pem寫成了publick.pem(哎。。。)
$ vi message.txt
$ cat message.txt
hello Vincent!!!
// 通過公鑰加密數據時,使用encrypt對文件進行加密
$ openssl rsautl -encrypt -in message.txt -inkey publick.pem -pubin -out enc.txt
// 此時查看該文件內容為亂碼
$ cat enc.txt
j??E]?a??d?kUE?&<
??I*??V/??pL[???ˋ?O?+?-?M??K???&??O??2???o34?:?$???6??C?L??,b?'M?S?k?0???A??3%?[I???1?????ps"%
// 通過私鑰解密數據
$ openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
// 已成功解密,正確顯示文件內容
$ cat dec.txt
hello Vincent!!!
// 通過私鑰加密數據時,要使用sign對文件進行重簽名
$ openssl rsautl -sign -in message.txt -inkey private.pem -out enc.bin
// 此時查看該文件內容同樣為亂碼
$ cat enc.bin
{???Ew?3?1E??,8-OA2?Is?:???:??@MU?????
?i1B???#??6????m?D(?t#/??? ??????????>(?>?^@?C??3??MQт?O%
// 通過公鑰解密數據
$ openssl rsautl -verify -in enc.bin -inkey publick.pem -pubin -out dec.bin
// 已成功解密,正確顯示文件內容
$ cat dec.bin
hello Vincent!!!
RSA用途及特點
到這里,大家都知道RSA相對比較安全,但是通過數學算法來加密和解密,效率比較低,所以一般RSA的主戰場是加密比較小的數據,比如對大數據進行對稱加密,再用RSA給對稱加密的KEY進行加密,或者加密Hash值,也就是數字簽名。
關于RSA數字簽名后面再慢慢闡述。該文章為記錄本人的學習路程,希望能夠幫助大家,也歡迎大家點贊留言交流!!!http://www.lxweimin.com/p/ad3d1dea63af