python实现RSA算法,对数据进行加密认证
RSA算法
- RSA
- 一、數(shù)學原理
- 二、實現(xiàn)代碼
- 1 生成素數(shù)
- 2 生成秘鑰
- 3 對數(shù)據(jù)進行加密、解密
- 總結
RSA
RSA是一種非對稱加密體制,由公鑰和私鑰組成,數(shù)學原理是實數(shù)域的模余法。在使用私鑰對數(shù)據(jù)進行加密后,可用公鑰對數(shù)據(jù)進行解密。
在RSA算法中,設公鑰為(D, N),私鑰為(E, N),加密過程可以表示為明文EmodN=密文明文^{E} \ mod\ N=密文 明文E?mod?N=密文
解密算法一致,把E換成D,密文DmodN=明文密文^{D} \ mod\ N=明文 密文D?mod?N=明文
當然,能這樣計算對N、E、D是有要求的。
RSA是目前公認的安全算法,對它進行破解需要進行大數(shù)的質(zhì)數(shù)分解,目前除了窮舉法沒有發(fā)現(xiàn)其他方法能計算,而窮舉法在足夠大的大數(shù)面前計算是需要非常漫長的時間的,因此當RSA算法采用的N、E、D足夠大時,就認為是安全的。目前來說需要N達到1024bits。
一、數(shù)學原理
歐拉函數(shù)的性質(zhì):
若n=qp,p和q是兩個質(zhì)數(shù),則φ(n)=(q?1)(p?1)n = qp,p和q是兩個質(zhì)數(shù),\ 則{\varphi}(n) = (q-1)(p-1)n=qp,p和q是兩個質(zhì)數(shù),?則φ(n)=(q?1)(p?1)
歐拉定理:若a與n互質(zhì),即gcd(a,n)=1,則aφ(n)≡1modngcd(a,n)=1, 則a^{\varphi(n)}\ {\equiv}\ 1\mod\ ngcd(a,n)=1,則aφ(n)?≡?1mod?n
進一步,若n是質(zhì)數(shù),an?1≡1modna^{n-1}\ {\equiv}\ 1\mod nan?1?≡?1modn,an≡amodna^{n}\ {\equiv}\ a\mod nan?≡?amodn
費馬小定理:若n是質(zhì)數(shù),a與n互質(zhì),,則an?1≡1modna^{n-1}\ {\equiv}\ 1 \mod \ nan?1?≡?1mod?n,
逆元:如果ab≡1modn,則a和b互為逆元ab\ {\equiv}\ 1\mod\ n, 則a和b互為逆元ab?≡?1mod?n,則a和b互為逆元
RSA加密的條件:
· n=p×qn = p{\times}qn=p×q
· L=φ(n)=(p?1)(q?1)L = {\varphi}(n) = (p-1)(q-1)L=φ(n)=(p?1)(q?1)
· 隨機選取 1<e<L,使得gcd(e,L)=11<e<L,使得gcd(e,L)=11<e<L,使得gcd(e,L)=1
·計算 ed≡1modLed\ {\equiv}\ 1\mod\ Led?≡?1mod?L
·公鑰對 =(n, d),私鑰對 =(n, e)
繼續(xù)設明文 = M,密文 = C,現(xiàn)在來證明可以用上述方法加解密的條件。
MEmodN=C,CDmodN=MM^{E}\ mod\ N = C,\ C^{D}\mod\ N = MME?mod?N=C,?CDmod?N=M
根據(jù)模法,CD?kN=MC^{D}\ -\ kN = MCD???kN=M,代回第一個式子,
(CD?kN)E≡1modN(C^{D}\ -\ kN)^{E}\ {\equiv}\ 1\mod\ N(CD???kN)E?≡?1mod?N CDE≡CmodNC^{DE}\ {\equiv}\ C\mod\ NCDE?≡?Cmod?N由于 E×D≡1modφ(N)E\times D\equiv 1\mod\ \varphi(N)E×D≡1mod?φ(N),也即 ED?kφ(N)=1ED-k\varphi(N) = 1ED?kφ(N)=1
若gcd(C, N) = 1,根據(jù)歐拉定理,Cφ(N)≡1modNC^{{\varphi}(N)}\ {\equiv}\ 1\mod\ NCφ(N)?≡?1mod?NCkφ(N)+1≡CmodNC^{k{\varphi}(N)+1}\ {\equiv}\ C\mod\ NCkφ(N)+1?≡?Cmod?NCED≡CmodNC^{ED}\ {\equiv}\ C \mod\ N CED?≡?Cmod?N若C與N不互質(zhì),由于N是兩個質(zhì)數(shù)的積,所以gcd(C,N)=q or gcd(C,N)=p。設 C=k1qorC=k2pC= k_{1}q\ or \ C=k_{2}pC=k1?q?or?C=k2?p,假設C = kp,而且gcd(m,q)=1,由歐拉定理和歐拉函數(shù)的性質(zhì),(kp)q?1≡1modq(kp)^{q-1} \ {\equiv} \ 1 \mod \ q(kp)q?1?≡?1mod?q((kp)q?1)k2(p?1)≡(kp)q?1≡1modq((kp)^{q-1})^{k_{2}(p-1)}\ {\equiv}\ (kp)^{q-1} \ {\equiv} \ 1 \mod \ q((kp)q?1)k2?(p?1)?≡?(kp)q?1?≡?1mod?q(kp)k2φ(n)≡1modq(kp)^{k_{2}{\varphi}(n)} \ {\equiv} \ 1 \mod \ q(kp)k2?φ(n)?≡?1mod?qCk2φ(n)?aq=1C^{k_{2}{\varphi}(n)}-aq = 1Ck2?φ(n)?aq=1兩邊同時乘上C,Ck2φ(n)+1=aCq+C=akpq+C=akN+C=k3N+CC^{k_{2}{\varphi}(n)+1}=aCq+C=akpq+C=akN+C=k_{3}N+CCk2?φ(n)+1=aCq+C=akpq+C=akN+C=k3?N+C也即 CED≡CmodNC^{ED}\ {\equiv}\ C\mod\ NCED?≡?Cmod?N,原式得證。
素數(shù)檢驗(Miller-Rabbin算法)
涉及到兩個定理:
5.1 費馬小定理:參見3,但是費馬小定理的逆定理不一定成立
5.2 二次探測定理:如果 p是一個素數(shù),0<x<p0<x<p0<x<p,則方程 x2≡1modpx^{2}\ {\equiv}\ 1 \mod px2?≡?1modp 的解為 x=1x=1x=1 或 x=p?1x=p-1x=p?1
算法內(nèi)容:
· 設一個數(shù)為x,分解為2st=x?12^{s}t\ =\ x-12st?=?x?1,t為x不斷除以2得到的最大奇數(shù)
· 隨機取a,a=ata=a^{t}a=at,對a進行s次平方(也即計算b=a2modx,a=bb = a^{2}\mod x,a = bb=a2modx,a=b),如果其中有次平方的結果為b=1而且此時a不為1或x-1,則不滿足二次探測定理
· 如果 ax?1modx≠1a^{x-1}\mod x {\neq}1ax?1modx?=1,則不滿足費馬小定理
如果可以,a取小于x的足夠多的質(zhì)數(shù)或者隨機選取a進行多次檢測。Miller-Rabbin算法只能保證x大概率是一個素數(shù),不過這個概率已經(jīng)足夠大了。
快速冪
計算axmodn=?a^x\mod n=?axmodn=?,當a和x很大的時候,中間結果超出存儲容量又或者數(shù)字太大計算復雜,此時需要快速計算這個指數(shù)模余值,可以如下進行:
對x分解為二進制形式,則有axmodn=a2bk+2bk?1+??????+2b0modn=((a2bkmodn)??????(a2b0modn))modna^{x}mod\ n= a^{2^{b_{k}}+2^{b_{k-1}}+······+2^{b_0}}mod\ n =((a^{2^{b_k}} mod\ n)······(a^{2^{b_0}} mod\ n))mod\ naxmod?n=a2bk?+2bk?1?+??????+2b0?mod?n=((a2bk?mod?n)??????(a2b0?mod?n))mod?n
二、實現(xiàn)代碼
重新看下RSA算法的流程,
· n=p×qn = p{\times}qn=p×q
· L=φ(n)=(p?1)(q?1)L = {\varphi}(n) = (p-1)(q-1)L=φ(n)=(p?1)(q?1)
· 隨機選取 1<e<L,使得gcd(e,L)=11<e<L,使得gcd(e,L)=11<e<L,使得gcd(e,L)=1
·計算 ed≡1modLed\ {\equiv}\ 1\mod\ Led?≡?1mod?L
·公鑰對 =(n, d),私鑰對 =(n, e)
由于RSA的安全性取決于n的大小,所以生成的p和q越大越好,那么需要
1 生成素數(shù)
用基礎算法列出1-1000的素數(shù),從2到x\sqrt xx?求x是非能被1和他自身外的其他數(shù)整除。
def createPrime():ret = []for i in range(1000):for j in range(2,ceil(sqrt(i))+1):if i % j == 0:breakif j == ceil(sqrt(i)):ret.append(i)return ret先實現(xiàn)快速冪算法,再用Miller-Rabbin算法生成一個大的素數(shù),這個大有多大看需求。
# 1000以內(nèi)的質(zhì)數(shù) prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347,349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883,887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]def quickPowerMod(a,x,n):# 計算a**x % nc = b = 1binary = bin(x)[2:]binary = reversed(binary)for it in binary:if it == '0':# 結果不動,乘子指數(shù)加一a = (a ** 2) % nelse:# 結果乘上當前權重,乘子指數(shù)加一b = (a * b) % na = (a ** 2) % nreturn bdef MillerRabin(num):# 偶數(shù)if num & 1 == 0:return False# 將num分解為 (2**s)*t = num-1s = 1# 這時t必定是偶數(shù),將其分解到為奇數(shù)t = num - 1while t & 1 == 0:s += 1t = t // 2for it in prime_list:if it >= num:breaka = quickPowerMod(it,t,num)# 二次探測定理for i in range(s):b = a * a % numif b == 1 and a != 1 and a != num-1:return Falsea = bif a != 1:# (it**t) 同余 1 mod num, 費馬小定理return Falsereturn Truedef createBigPrime():pMin = 10 ** 54pMax = 10 ** 64a = random.randint(pMin,pMax)while not MillerRabin(a):a = random.randint(pMin, pMax)return a2 生成秘鑰
接下來編寫函數(shù)生成公鑰私鑰對,求逆元的時候有幾種算法,由于明文和N關系未知,選取擴展歐幾里得算法,又需要求最大公因子和最小公倍數(shù)的函數(shù),這兩個很簡單,直接上代碼。
def gcd(a,b):if a % b == 0:return belse:return gcd(b, a % b)def lcm(a,b):c = gcd(a, b)return a * b // cdef inverseGCD(a,b):# 遞推求擴展歐幾里得算法if b == 0:return 1, 0else:k = a // bx2, y2 = inverseGCD(b, a % b)x1, y1 = y2, x2 - k * y2# 注意x1可能為負,在外面再求一次模return x1, y1def createKeys():q = createBigPrime()p = createBigPrime()n = q * p# n的歐拉函數(shù)L = (p - 1) * (q - 1)e = random.randint(2,L)while gcd(e,L) != 1:e = random.randint(2,L)# 計算e * d 同余 1 mod L# 擴展歐幾里得算法求逆元d, _ = inverseGCD(e,L)d = d % L#d = e**(L-2)with open('e.txt', 'w') as f:f.write(str(e))with open('d.txt', 'w') as f:f.write(str(d))with open('n.txt', 'w') as f:f.write(str(n))return n, e, d3 對數(shù)據(jù)進行加密、解密
有了私鑰對,加密只是進行一個求快速冪的過程。
m = 8916534261681675 n,e,d = createKeys() print('私鑰對:\n',n,e) print('公鑰對:\n',n,d) en = quickPowerMod(m,e,n) print('原消息: ', m) print('加密后:', en) de = quickPowerMod(en,d,n) print('解密后:', de)看下結果
已經(jīng)完成正確的加解密!
總結
RSA算法用到數(shù)論、離散數(shù)學的基礎,加密速度慢,而且每次加密過程中消息大小M不能大于N。但RSA算法是公認非常安全的算法。
如果想對大小超出N的消息加密,一般需要先用DES、SHA等對原消息計算成一定長度的摘要,再對摘要進行RSA加密。
總結
以上是生活随笔為你收集整理的python实现RSA算法,对数据进行加密认证的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++学习之路 | PTA乙级—— 10
- 下一篇: mysql binlog过期策略_对存在