信息安全-5:RSA算法詳解(已編程實現)[原創]

 轉發註明出處:http://www.cnblogs.com/0zcl/p/6120389.htmlhtml

 

背景介紹

1976年之前,全部的加密方法都是同一種模式:python

  (1)甲方選擇某一種加密規則,對信息進行加密;算法

  (2)乙方使用同一種規則,對信息進行解密。編程

 

因爲加密和解密使用一樣規則(簡稱"密鑰"),這被稱爲"對稱加密算法"(Symmetric-key algorithm)。安全

這種加密模式有一個最大弱點:甲方必須把加密規則告訴乙方,不然沒法解密。保存和傳遞密鑰,就成了最頭疼的問題。網絡

1976年,兩位美國計算機學家Whitfield Diffie 和 Martin Hellman,提出了一種嶄新構思,能夠在不直接傳遞密鑰的狀況下,完成解密。這被稱爲"Diffie-Hellman密鑰交換算法"。這個算法啓發了其餘科學家。人們認識到,加密和解密可使用不一樣的規則,只要這兩種規則之間存在某種對應關係便可,這樣就避免了直接傳遞密鑰。app

這種新的加密模式被稱爲"非對稱加密算法"dom

  (1)乙方生成兩把密鑰(公鑰和私鑰)。公鑰是公開的,任何人均可以得到,私鑰則是保密的。ide

  (2)甲方獲取乙方的公鑰,而後用它對信息加密。函數

  (3)乙方獲得加密後的信息,用私鑰解密。

 

若是公鑰加密的信息只有私鑰解得開,那麼只要私鑰不泄漏,通訊就是安全的。

1977年,三位數學家Rivest、Shamir 和 Adleman 設計了一種算法,能夠實現非對稱加密。這種算法用他們三我的的名字命名,叫作RSA算法。從那時直到如今,RSA算法一直是最廣爲使用的"非對稱加密算法"。絕不誇張地說,只要有計算機網絡的地方,就有RSA算法。

這種算法很是可靠,密鑰越長,它就越難破解。根據已經披露的文獻,目前被破解的最長RSA密鑰是768個二進制位。也就是說,長度超過768位的密鑰,還沒法破解(至少沒人公開宣佈)。所以能夠認爲,1024位的RSA密鑰基本安全,2048位的密鑰極其安全。

 

 

RSA算法原理

 

RSA算法須要一些數學知識,不過別慫,不難的。我總結了一下,大概須要如下三部分的知識:

  • 互質關係(這,很簡單)
  • 歐拉公式(難,我是直接記公式的)
  • 模反元素(不難的)

 

接下來講下每一個部分的內容:

一、互質關係:若是兩個正整數,除了1之外,沒有其餘公因子,咱們就稱這兩個數是互質關係(coprime)。好比,15和32沒有公因子,因此它們是互質關係。這說明,不是質數也能夠構成互質關係。

二、先說下 歐拉函數:φ(n)爲比n小但與n互素的正整數個數,稱爲n的歐拉函數。對任一素數p, 有φ(n)=p-1,而對於兩個不一樣的素數p和q,則對n=pq,能夠證實φ(n)=φ(pq)=(p-1)(q-1)=φ(p)*φ(q)

三、模反元素:如何求模反元素(逆元),用展轉相除法,我在上一篇博客<信息安全-4:公鑰密碼體制之揹包算法[原創]>有說,看了必定會懂的!

 

上面3點必定要GET,否則不用往下看了~~

 

 

 

RSA算法的過程

 

RSA算法可概括以下:

  1. 選擇兩個素數p和q,計算n=p*q,φ(n)=(p-1)(q-1),選擇整數e,使gcd(φ(n), e)=1,1<e<φ(n),計算逆元d=e-1modφ(n),因而獲得公鑰KU={e, n},私鑰={d, n},而把p和q丟棄(PS:gcd(φ(n), e)=1 表示最大公約數爲1,下面編程有用到~)。
  2. 加密(用公鑰KU):明文M<n, 密文:C=mmod n
  3. 解密(用私鑰KR):密文:C, 明文:M=Cd mod n

 

上面過程很重要!!! 剛開始看會有點懵逼,看下面的例子,必定會懂!

 

咱們經過一個例子,來理解RSA算法。假設Alice想發送明文9726給Bob,這之間的過程是怎樣的?又是怎樣生成公鑰和私鑰呢?

 

(1)Bob生成密鑰 

Bob選擇兩個互異素數p=101和q=113,計算:n=pq=101*113=11413, φ(n)=(p-1)(q-1)=100*112=11200

因爲加密密鑰e必須與φ(n)沒有公因子,假設Bob隨機選擇了e=3533,則用展轉相除法可求得: d=e-1=3533-1 mod 11200=6597

因而Bob公佈他的公鑰KU={3533, 11413}, 將私鑰KR={6597, 11413}保密。

 

(2)Alice加密信息

因爲Bob的公鑰是公開的,任何人均可獲得,所以Alice使用Bob的公鑰來加密即將發送給Bob的明文信息。

Alice計算: 97263533 mod 11413=5761, 而後在一個信道上發送密文5761.

 

(3)Bob解密密文

當Bob接收到密文5761時,他用他的私鑰進行解密。

Bob計算: 57616597 mod 11413=9726, 這樣Bob就獲得Alice發給他的明文信息了!!!

 

 

 

RSA算法編程實現

 

流程圖

我畫的流程圖網址: https://www.processon.com/diagraming/583fb2c0e4b0d0d77bcfa514

 

ReadMe:

  1. 運行環境爲python3.4   Windows8.1, 程序代碼用Python語言寫的
  2. 質數P,Q是我本身給出的,固然也能夠隨機生成
  3. 運行時,必須先加密再解密,由於先加密纔有逆元給解密模塊進行運算
  4. 運行時有一些測試打印出來,爲了方便了解程序運行過程,我這裏就沒有去除。

 

 

源代碼

  1 #RSA加密算法
  2 
  3 import random
  4 # p,q是兩個不一樣的素數n=pq,按理說應該隨機產生,這裏我用p=101,q=103爲例
  5 
  6 P = 101
  7 Q = 113
  8 N = P * Q
  9 global _E  # 把逆元定義爲全局變量,才能在解密模塊調用
 10 _E = 0     #初始爲0
 11 
 12 #歐拉公式:若是n是質數,則 φ(n)=n-1 。由於質數與小於它的每個數,都構成互質關係
 13 F = (P-1) * (Q-1)
 14 
 15 
 16 #求最大公約數,若最大公約數是1,且m,n>1,m與n不等,則說明m,n互質
 17 def comm_div(m, n):      #m>n
 18     temp = m % n
 19     while(temp != 0):
 20         m = n
 21         n = temp
 22         temp = m % n
 23     if n == 1:         #說明互質,返回True
 24         return True
 25 
 26 
 27 # 在1-9999之間隨機選擇一個整數e,條件是1< e < F,且e與F 互質
 28 # 互質即說明e,F的公因子有且僅有1
 29 def e_product():
 30     while True:
 31         rand = random.randrange(2, F)
 32         if comm_div(F, rand):
 33             e = rand
 34             return e
 35 
 36 
 37 #用展轉相除法求質數e關於歐拉公式F的逆元
 38 def _e_product(e, F):
 39     a_list = []
 40     m = F
 41     n = e
 42     temp = m % n
 43 
 44     while (temp != 0):
 45         a = (m - temp) / n
 46         a_list.append(a)
 47         m = n
 48         n = temp
 49         temp = m % n
 50     print("a_list:", a_list)
 51     a_list.reverse()    #逆序
 52     print("a_list_reverse:", a_list)
 53     b_list = []
 54     b_list.append(1)
 55     b_list.append(a_list[0])
 56     print("(最初插入的兩個1及a_list[0])b_list:", b_list)
 57     for i in range(len(a_list)-1):
 58         b = b_list[-1] * a_list[i+1] + b_list[-2]
 59         b_list.append(b)
 60 
 61     print("b_list", b_list)
 62     #a_list存放的是商數,若是商數個數是偶數 b_list[-1]即爲所求逆元
 63     #若爲奇數,F-b_list[-1]爲所求的逆元
 64     if len(a_list) % 2 == 0:   #偶數
 65         return b_list[-1]
 66     else:
 67         return F - b_list[-1]
 68 
 69 
 70 #傳入明文(數字)和公鑰,進行加密,返回密文
 71 def core_encryption(clear_text, e, N):
 72     clear = clear_text
 73     for i in range(e-1):
 74         clear_text = clear_text  * clear
 75     cipher_text = clear_text % N
 76     return cipher_text
 77 
 78 
 79 def encryption(clear_text):
 80     clear_text = int(clear_text)
 81     e = e_product()
 82     print("隨機產生的e:%s" % e)
 83     global _E       #對全局變量進行從新賦值,須要global
 84     _E = _e_product(e, F)
 85     # print("逆元_e:", _E)
 86     # print("逆元類型:",type(_E))
 87     print("公鑰KU:%d,%d\n私鑰KR:%d,%d" % (e,N, _E,N))
 88     cipher_text = core_encryption(clear_text,e,N)
 89     return cipher_text
 90 
 91 
 92 #根據以前加密生成的私鑰進行解密,因此必須先有加密才行的
 93 def decryption(cipher_text, _e, N):
 94     cipher_text = int(cipher_text)
 95     cipher = cipher_text
 96     # print(_e)
 97     # print("逆元_e類型:",type(_e))
 98     for i in range(_e-1):
 99         cipher_text = cipher_text * cipher
100     clear_text = cipher_text % N
101     return clear_text
102 
103 
104 if __name__ == "__main__":
105     while True:
106         print("必須先加密後解密!".center(50, "-"))
107         choice = input("Input E for encryption or D for decryption:")
108         if choice == "E":
109             clear_text = input("請輸入明文(只容許數字):")
110             if clear_text.strip().isalnum():
111                 print("加密成功!密文爲:%d" % encryption(clear_text))
112         if choice == "D":
113             cipher_text = input("請輸入密文:")
114             if cipher_text.strip().isalnum():
115                 print("解密成功!明文爲:%d" % decryption(cipher_text, _E, N))
View Code

 

 

問題

在測試時我遇到了下面這個問題

 1 C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/xingxi/playfair/RSA.py
 2 --------------------必須先加密後解密!---------------------
 3 Input E for encryption or D for decryption:E
 4 請輸入明文(只容許數字):9726
 5 隨機產生的e:2147
 6 a_list: [5.0, 4.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0]
 7 a_list_reverse: [1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 4.0, 5.0]
 8 (最初插入的兩個1及a_list[0])b_list: [1, 1.0]
 9 b_list [1, 1.0, 2.0, 3.0, 8.0, 11.0, 19.0, 30.0, 49.0, 79.0, 128.0, 591.0, 3083.0]
10 公鑰KU:2147,11413
11 私鑰KR:3083,11413
12 加密成功!密文爲:5200
13 --------------------必須先加密後解密!---------------------
14 Input E for encryption or D for decryption:D
15 請輸入密文:5200
16 Traceback (most recent call last):
17   File "C:/Users/Administrator/PycharmProjects/xingxi/playfair/RSA.py", line 116, in <module>
18     print("解密成功!明文爲:%d" % decryption(cipher_text, _E, N))
19   File "C:/Users/Administrator/PycharmProjects/xingxi/playfair/RSA.py", line 99, in decryption
20     for i in range(_e-1):
21 TypeError: 'float' object cannot be interpreted as an integer
22 
23 Process finished with exit code 1

如今已經解決了,問題出在了下面第6行代碼,rang()函數裏面不能是float型,只須要int(_e-1)轉型便可解決!

1 def decryption(cipher_text, _e, N):
2     cipher_text = int(cipher_text)
3     cipher = cipher_text
4     # print(_e)
5     # print("逆元_e類型:",type(_e))
6     for i in range(_e-1):   
7         cipher_text = cipher_text * cipher
8     clear_text = cipher_text % N
9     return clear_text

你可能會說,毛線,這麼簡單的坑你都跳(鄙視臉)。

好吧,這都怪我在這以前輸出了一條測試print("_e:%d" % _e),而後我運行時看到輸出的是整型,就蒙比了,心想:明明是int型,怎麼會爆錯說float型!!!這大概就是所謂的被本身挖的坑坑到懷疑人生吧~~

 

 

 測試(爲了方便我往後再來看,一些打印測試我沒有去除)

 1 C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/xingxi/playfair/RSA.py
 2 --------------------必須先加密後解密!---------------------
 3 Input E for encryption or D for decryption:E
 4 請輸入明文(只容許數字):9726
 5 隨機產生的e:4031
 6 a_list: [2.0, 1.0, 3.0, 1.0, 1.0, 17.0, 2.0, 1.0, 3.0]
 7 a_list_reverse: [3.0, 1.0, 2.0, 17.0, 1.0, 1.0, 3.0, 1.0, 2.0]
 8 (最初插入的兩個1及a_list[0])b_list: [1, 3.0]
 9 b_list [1, 3.0, 4.0, 11.0, 191.0, 202.0, 393.0, 1381.0, 1774.0, 4929.0]
10 公鑰KU:4031,11413
11 私鑰KR:6271,11413
12 加密成功!密文爲:325
13 --------------------必須先加密後解密!---------------------
14 Input E for encryption or D for decryption:D
15 請輸入密文:325
16 解密成功!明文爲:9726
17 --------------------必須先加密後解密!---------------------
18 Input E for encryption or D for decryption:E
19 請輸入明文(只容許數字):25
20 隨機產生的e:6403
21 a_list: [1.0, 1.0, 2.0, 1.0, 75.0, 2.0]
22 a_list_reverse: [2.0, 75.0, 1.0, 2.0, 1.0, 1.0]
23 (最初插入的兩個1及a_list[0])b_list: [1, 2.0]
24 b_list [1, 2.0, 151.0, 153.0, 457.0, 610.0, 1067.0]
25 公鑰KU:6403,11413
26 私鑰KR:1067,11413
27 加密成功!密文爲:10272
28 --------------------必須先加密後解密!---------------------
29 Input E for encryption or D for decryption:D
30 請輸入密文:10272
31 解密成功!明文爲:25
32 --------------------必須先加密後解密!---------------------
33 Input E for encryption or D for decryption:
View Code

 

 

 

注:RSA算法背景參考自http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

    博客參考書籍:信息安全概論(凌捷  謝贊福   編著)

    接下來一個月信息安全方面可能最多會再寫一篇博客, 重心會放在人工智能和操做系統!fight!

相關文章
相關標籤/搜索