对称加密
1976年以前,所有的加密方法都是同一种模式: (1)甲方选择某一种加密规则,对信息进行加密; (2)乙方使用同一种规则,对信息进行解密。 由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法"
非对称加密算法
1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为"Diffie-Hellman密钥交换算法" 加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。 (1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。 (2)甲方获取乙方的公钥,然后用它对信息加密。 (3)乙方得到加密后的信息,用私钥解密。 如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
RSA算法历史
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。 目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。
RSA涉及基础数论:
互质关系: 如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime) 如,15和32没有公因子,所以它们是互质关系。这说明,不是质数也可以构成互质关系。 基础结论:
任意两个质数构成互质关系,比如13和61。 一个数是质数,另一个数只要不是前者的倍数,两者就构成互质关系,比如3和10。 如果两个数之中,较大的那个数是质数,则两者构成互质关系,比如97和57。 1和任意一个自然数是都是互质关系,比如1和99。 p是大于1的整数,则p和p-1构成互质关系,比如57和56。 p是大于1的奇数,则p和p-2构成互质关系,比如17和15。
欧拉函数:
问题:任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系? 计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。 φ(n) 的计算方法并不复杂,但是为了得到最后那个公式,需要一步步讨论。 第一种情况:如果n=1,则 φ(1) = 1 。因为1与任何数(包括自身)都构成互质关系。 第二种情况:如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。 第三种情况:如果n是质数的某一个次方,即 n = p^k (p为质数,k为大于等于1的整数),则φ(p^k) = p^k - p(k-1)=p k(1-1/p) 第四种情况: 如果n可以分解成两个互质的整数之积,n = p1 × p2,则: φ(n) = φ(p1p2) = φ(p1)φ(p2) 第五种情况:因为任意一个大于1的正整数,都可以写成一系列质数的积。
欧拉定理
如果两个正整数a和n互质,则n的欧拉函数 φ(n) 可以让下面的等式成立:a ^ φ(n) ≡ 1(mod n) 也就是说,a的φ(n)次方被n除的余数为1。或者说,a的φ(n)次方减去1,可以被n整除。 比如,3和7互质,而7的欧拉函数φ(7)等于6,所以3的6次方(729)减去1,可以被7整除(728/7=104)。
模反元素
如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1。ab ≡ 1 (mod φ(n)) 这时,b就叫做a的"模反元素"。
密钥生成的步骤
第一步,随机选择两个不相等的质数p和q。 第二步,计算p和q的乘积n。 第三步,计算n的欧拉函数φ(n)。 φ(n) = (p-1)(q-1) 第四步,随机选择一个整数e,条件是1 (实际应用中,常常选择65537。) 第五步,计算e对于φ(n)的模反元素d。
加密和解密
(1)加密要用公钥 (n,e) (2)解密要用私钥(n,d)
示例:
from tkinter import *
import rsa
import base64
def GenerateKey ( ) :
( public_key, private_key) = rsa. newkeys( 1024 )
print ( "\n生成公钥:" + public_key. save_pkcs1( ) . decode( 'utf8' ) )
print ( "\n生成私钥:" + private_key. save_pkcs1( ) . decode( 'utf8' ) )
publicKeyText. delete( 0.0 , END)
publicKeyText. insert( END, public_key. save_pkcs1( ) . decode( 'utf8' ) )
privateKeyText. delete( 0.0 , END)
privateKeyText. insert( END, private_key. save_pkcs1( ) . decode( 'utf8' ) )
def EncryptionByPublickey ( ) :
public_key_str = publicKeyText. get( "0.0" , "end" ) . encode( encoding= "utf-8" )
public_key = rsa. PublicKey. load_pkcs1( public_key_str)
entry_str = entryText. get( "0.0" , "end" ) . encode( encoding= "utf-8" )
encrypt_msg = rsa. encrypt( entry_str, public_key)
print ( "公钥加密后的文本为:\n" + base64. encodebytes( encrypt_msg) . decode( 'utf8' ) )
outputText. delete( 0.0 , END)
outputText. insert( END, base64. encodebytes( encrypt_msg) . decode( 'utf8' ) )
def DecryptionByPrivatekey ( ) :
private_key_str = privateKeyText. get( "0.0" , "end" ) . encode( encoding= "utf-8" )
private_key = rsa. PrivateKey. load_pkcs1( private_key_str)
entry_str = entryText. get( "0.0" , "end" ) . encode( encoding= "utf-8" )
encrypt_msg = base64. decodebytes( entry_str)
outputText. delete( 0.0 , END)
try :
decrypt_msg = rsa. decrypt( encrypt_msg, private_key)
print ( "私钥解密后的文本为:\n" + decrypt_msg. decode( 'utf8' ) )
outputText. insert( END, decrypt_msg. decode( 'utf8' ) )
except :
decrypt_msg = "私钥解密失败"
print ( decrypt_msg)
outputText. insert( END, decrypt_msg)
window = Tk( )
window. title( "RSA加密解密程序" )
frame = Frame( window)
frame. pack( )
label = Label( frame, text= "生成公钥为(公钥用于加密):" )
label. grid( row= 1 , column= 1 , columnspan= 4 )
publicKeyText = Text( frame, width= 50 , height= 8 )
publicKeyText. grid( row= 2 , column= 1 , columnspan= 4 )
label = Label( frame, text= "生成私钥为(私钥用于解密):" )
label. grid( row= 3 , column= 1 , columnspan= 4 )
privateKeyText = Text( frame, width= 50 , height= 12 )
privateKeyText. grid( row= 4 , column= 1 , columnspan = 4 )
btGenerateKey = Button( frame, text = "生成公钥/私钥(点击我生成新的)" , command= GenerateKey)
btGenerateKey. grid( row = 5 , column = 1 , columnspan = 4 )
label = Label( frame, text = "请输入加密/解密的文本:" )
label. grid( row = 6 , column = 1 , columnspan = 4 )
entryText = Text( frame, width= 50 , height= 5 )
entryText. grid( row = 7 , column = 1 , columnspan = 4 )
btEncryptionByPublickey = Button( frame, text= "公钥加密" , command= EncryptionByPublickey)
btEncryptionByPublickey. grid( row = 8 , column = 1 , pady = 10 )
btDecryptionByPrivatekey = Button( frame, text = "私钥解密" , command= DecryptionByPrivatekey)
btDecryptionByPrivatekey. grid( row= 8 , column= 4 )
outputText = Text( frame, width= 50 , height= 5 )
outputText. grid( row= 9 , column= 1 , columnspan= 4 )
label= Label( frame, text= "结果生成。。" )
label. grid( row= 10 , column= 1 , columnspan= 4 )
print ( "欢迎使用……" )
GenerateKey( )
mainloop( )
print ( "欢迎再次使用……" )