RSA的數學及算法實現

近段時間一直在RSA,PKI, CA,Certificate裏混,恰恰RSA牽扯到了數論的一些知識,想一想是否能用代碼來完整的實現一下,也算作一個總結php

整除: a整除b, 表示爲 a|b => b = ka => b%a=0html

質數:除1和自身外,不被其它數整除python

分析:判斷一個質數只有該數與小於它的數取餘都不爲0, 則能夠判斷此數爲質數算法

1 #!/usr/bin/env python
  2 import math
  3 def prime(number):
  4     for i in range(2,number):
  5         if number%i == 0:
  6             break
  7     if i == number-1:
  8         return True
  9     else:
 10         return False         
 11 number = int (raw_input('please input a number:'))
 12 
 13 print prime(number)
 14 print prime_fast(number)

分析:若是一個數是合數,n = p*q, 若是 p<=sqrt(n),那麼q>=sqrt(n), 若是sqrt(n)+1之內沒有數能夠整除n,能夠判定大於(sqrt(n),n)也不會有數能夠整除n安全

15 def prime_fast(number):
16     N = int(math.sqrt(number)+1)
17     for i in range(2,N): 
18         if number % i == 0:
19             break
20     if i == N-1:
21         return True
22     else:
23         return False

最大公約數:能同時整除a和b的最大值,表示爲gcd(a,b)函數

即 a % gcd(a,b) = 0 && b % gcd(a,b)=0 && 最大的公約數ui

分析: 歐幾里德定理 gcd(a,b) = gcd(b, a mod b)加密

證實: 
   設 a = q * b + r                     q爲整數, r爲餘數
   設 d 爲 a, b 的公約數
   則 d|a=m,  d|b= n, (m,n爲整數)
   由於 r = a - q*b
   因此 d|r = d|a -q*d|b = m - q*n =k   仍爲整數
   由於 d|b, d|r都爲整數
   因此 d是(r,b)的公約數
   因爲d是任意假設的,而d便是(a,b)的公約數,又是(b,r)的公約數,可得(a,b)與(b,r)的公約數相同
   因此最大公約數也相同表示爲 gcd(a,b)=gcd(b,r)=gcd(b,a mod b)

經過這個定理,算gcd(a,b)只須要計算gcd(b, a %b)就能夠,那麼數學的表示:.net

r_0=a, r_1=b
r_0 = q_1 * r_1 + r_2
r_1 = q_2 * r_2 + r_3
r_2 = q_3 * r_3 + r_4
...
r_i = q_(i+1) * r_(i+1) + r_(i+2)
...
r_(n-2) = q_(n-1) * r_(n-1) + r_n  (r_n爲最大公約數)
r_(n-1) = q_n * r_n + 0

證實1: r_n爲a, b的公約數unix

由於 r_(n-1) = q_n * r_n
因此 r_n | r_(n-1)                 ........q_n
由於 r_(n-2) = q_(n-1) * r_(n-1) + r_n
因此 r_n | r_(n-2)                 ........q_(n-1)*q_n+1
能夠推斷 r_n | r_1,  r_n | r_0 => r_n | a, r_n | b
r_n 爲 a, b 的公約數

證實2: r_n 爲a, b的最大公約數

設a, b的最大公約數g(a,b) = g
則 g | a,  g | b => g | r_0, g | r_1
由於 r_0 = q_1 * r_1 + r_2
因此 g | r2  ..............r_0/g-q_1*r_1/g爲整數
因此 g | r_n 
因此 r_n >= g
由於g 是最大公約數,因此r_n是最大公約數

證實3: r_(n+1)=0

r_0 = q_1 * r_1 + r_2
r_1 = q_2 * r_2 + r_3
...
r_i = q_(i+1)*r_(i+1)+r_(i+2)
...
r_(n-2) = q_(n-1) * r_(n-1) + r_n

r_2是r_1的餘數,因此r_2<r_1
r_3是r_2的餘數,因此r_3<r_2
...
r_0>r_1>r_2>r_i...>r_(n-1)
因爲都是整數,所以確定存一個r_(n+1)=0,算法終止

歐幾里德算法

def gcd(a,b):
    「a = q * b + r」               
    if a<b:
        a,b = b,a
    while (a%b!=0):               #餘數最終會等於0
        a,b = b,a%b               #b = (a%b)*r + r_1
    return b

擴展歐幾里德算法

分析: a * x + b * y  = gcd(a,b)

def exgcd(a,b):
    "ax+by=gcd(a,b)"
    if b==0:
        return (1,0)
    #a*x1 + b*y1 = a
    x1=1
    y1=0
    #a*x2 + b*y2 = b
    x2=0
    y2=1
    while b!=0:
        q = a/b
        #gcd(a,b)=gcd(b,a%b)
        a,b = b, a%b
        #x_i = x_(i-2) - a/b*x_(i-1)
        x1,x2 = x2, x1-q*x2                #此時的x1是x2, x2實際上是x3 下一次的賦值 x3=x1-q*x2
        #y_i = y_(i-2)- a/b*y_(i-1)
        y1,y2 = y2,y1-q*y2                 #因爲y的值取決於前兩次的值,而初值又給定,所以y值確定能算出,b是循環終止,因此能夠算出一對(x,y)
    return (x1,y1,a)

歐拉函數:

def oula(number):
    counter = 0
    for i in range(1,number):
        if gcd(i,number)==1:  #gcd(a,b)=1, a  and b relatively prime
            counter+=1
    return counter

RSA加解密的數學表示

加密 m ^ e mod n = c
解密 c ^ d mod n = m
代入 (m ^ e) ^ d mod n = m 
得   m ^ (e*d) mod n = m
=>   m ^ (e*d-1) mod n = 1
歐拉定理: m ^ φ(n) mod n = 1
所以 e*d-1 = k*φ(n)
e * d - k*φ(n) = 1
a * x + b * y = 1

例子:

Alice發一個信息給Bob, 該信息的數數爲 m = 89

Bob首先要生成公鑰(n,e)和私鑰(n,d)

Bob 選取 p=53, q=59 做爲 n = p * q = 3127
Bob 任意選取 e=3
此時能夠計算出 φ(n)=(p-1)(q-1)=52*58=3016, 由於p,q是質數,一樣也能夠經過代碼計算oula(3127)=3016
計算私鑰:e * d - k * φ(n) = 1
         3 * d + 3016*k = 1                由於並不在意k的值,但代入代碼中的(a,b)爲正數
經過代碼計算得出 exgcd(3,3016)     d,k = -1005,1     d=-1005是個負數因此須要尋找另外一個解
         3 *(3016-1005) + 3016*1 - 3*3016       d,k = 2011,-2  d = 2011
         只要給出3016的整數倍,k就是整數,就是另外一個解
Bob給Alice     (n=3127,e=3)
Bob本身保存私鑰  (n=3127,d=2011)

Alice對信息進行加密

m ^ e mod n = c
89 ^ 3 mod 3127 = 1394
把 c=1394傳給Bob,這個是用(n,e)加密過的信息c,原始信息爲m

Bob用私鑰解密

c ^ d mod n = 1394 ^ 2011 mod 3127 = 89L
獲得原信息 m

RSA的安全性

知道 n, e, 能否算得出d,其中最重要的就是一個參數 φ(n),雖然我有代碼計算 oula(number),可是這並非那麼容易的事,運行程序隨着當number的位數增長,時間成倍的增長,暴力的破解是能夠破解,但若是要你花一萬年的時間呢,得不嘗失了,目前最多也就破了768位,當咱們的n是1024位時基本就是安全的,爲何選p,q爲質數呢,也在於當p,q爲質數時,算φ(n)=(p-1)(q-1),但若是你不知道p,q,由n來因式分解的話,就等死吧

參考:

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26403844&id=5065983
http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
http://www.wikiwand.com/zh/碾轉相除法
相關文章
相關標籤/搜索