23、Python之加密&解密以及加签&验签
一、rsa基本原理
关于加密与加签其目的就是为了保证数据传输的安全性,加签的作用就像签名,告诉别人这个就是我发的数据,别人无法模仿,加密的作用是传输的报文是一串密文,他人无法看懂什么意思,下图描述了使用rsa进行加签,加密,验签,解密的过程。
AB双方生成2对秘钥,A用自己的私钥进行签名(表示是自己发的数据),然后用B的公钥进行加密(这个数据是密文,第三方压根看不懂),B在接收到A发过来的数据时,先用B的私钥进行解密(嘿嘿,只有我能解密),随后用A的公钥进行验签(嗯,就是A发过来的数据),最终使用A传过来的明文进行后续业务处理(上图中B端数据描述不太准确,忽略,懒的画图)。后续通信亦是如此!
二、python中rsa操作
python中使用rsa模块,首先我们要先生成2对秘钥值,在python中使用下面代码生成秘钥值(记得生成2对)。
1 import rsa 2 3 import base64 4 # 生成密钥 5 (pubkey, privkey) = rsa.newkeys(1024) 6 # 保存密钥 7 with open('public.pem', 'w+') as f: 8 f.write(pubkey.save_pkcs1().decode()) 9 10 with open('private.pem', 'w+') as f: 11 f.write(privkey.save_pkcs1().decode())
生成的2对秘钥如下:
1 import rsa,json 2 import base64 3 def encrypt_data(message): 4 data = {} 5 data['message'] = message 6 print("明文:%s" % data) 7 #用A的私钥加签 8 str_data = json.dumps(data) 9 with open('a_private.pem', 'r') as f: 10 privkey = rsa.PrivateKey.load_pkcs1(f.read().encode()) 11 signature = rsa.sign(str_data.encode('utf-8'), privkey, 'SHA-1') 12 sign = base64.b64encode(signature) 13 data['sign'] = sign.decode() 14 str_data = json.dumps(data) 15 16 #用B的公钥加密 17 finally_data = {} 18 PAGE_SIZE = 110 # 每页大小 因为加密最大长度为117 需要进行切片加密 19 data_lengh = len(str_data) - 1 20 pages = data_lengh // PAGE_SIZE if (data_lengh % PAGE_SIZE) == 0 else data_lengh // PAGE_SIZE + 1 21 with open('b_public.pem', 'r') as f: 22 pubkey = rsa.PublicKey.load_pkcs1(f.read().encode()) 23 for page in range(pages): 24 if page < pages - 1: 25 value = str_data[PAGE_SIZE * page:PAGE_SIZE * (page + 1)] 26 else: 27 value = str_data[PAGE_SIZE * page:] 28 encrypt_data = rsa.encrypt(value.encode('utf-8'),pubkey) 29 finally_data[page] = base64.b64encode(encrypt_data).decode() 30 31 print("加签后的密文:" , finally_data) 32 return finally_data 33 34 def decry_data(encrypt_message): 35 #B的私钥解密 36 with open('b_private.pem', 'r') as f: 37 privkey = rsa.PrivateKey.load_pkcs1(f.read().encode()) 38 final_data = '' 39 for index in encrypt_message: 40 temp_data = base64.b64decode(encrypt_message[index]) 41 data = rsa.decrypt(temp_data,privkey).decode() 42 final_data = final_data + data 43 print("解密后的明文:%s" % final_data) 44 #A的公钥验签 45 with open('a_public.pem', 'r') as f: 46 pubkey = rsa.PublicKey.load_pkcs1(f.read().encode()) 47 message = {} 48 final_data = json.loads(final_data) 49 message['message'] = final_data['message'] 50 sign = base64.b64decode(final_data['sign']) 51 message_str = json.dumps(message) 52 result = rsa.verify(message_str.encode("utf-8"), sign, pubkey) 53 print("明文:%s,验签结果:%s" % (message_str,result)) 54 data = encrypt_data("hi,I am A") 55 decry_data(data)
上面的代码即实现了上图的通信,下面描述一下整个过程:
A端要发送的数据是:data=['message'] = 'hi,I am A'。于是A开始进行安全性操作,
第一步:用a自己的私钥进行加签,获得签名值sign,之后又用base64做了一个编码,然后将签到值存放在data中。
第二步,进行加密,由于rsa只能支持117位的数据的加密,因此需要对进行加密的数据进行切割再加密,对切割的每段进行加密之后再使用base64进行编码最终将加密后的数据发送出去。
B端接收数据:
第一步,对每段加密的报文进行base64解码,然后再进行rsa解密。
第二步,拿到解密后的报文,其中包含A传输过来的明文和签名值,对签名值进行base64进行解码,然后对A发送过来的数据进行验签,一切顺利后,即认为报文的是正确的且安全性的。
注解:在这个过程中存在很多编码的问题,应当小心。