23、Python之加密&解密以及加签&验签

2021-02-20 07:08发布

一、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())
View Code

生成的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)
View Code

上面的代码即实现了上图的通信,下面描述一下整个过程:

 A端要发送的数据是:data=['message'] = 'hi,I am A'。于是A开始进行安全性操作,

        第一步:用a自己的私钥进行加签,获得签名值sign,之后又用base64做了一个编码,然后将签到值存放在data中。

        第二步,进行加密,由于rsa只能支持117位的数据的加密,因此需要对进行加密的数据进行切割再加密,对切割的每段进行加密之后再使用base64进行编码最终将加密后的数据发送出去。

B端接收数据:

        第一步,对每段加密的报文进行base64解码,然后再进行rsa解密。

        第二步,拿到解密后的报文,其中包含A传输过来的明文和签名值,对签名值进行base64进行解码,然后对A发送过来的数据进行验签,一切顺利后,即认为报文的是正确的且安全性的。

注解:在这个过程中存在很多编码的问题,应当小心。

标签: