python RSA、AES 加密解密

普通的RSA加密、及AES CBC加密

1
pip install pycryptodome
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# time : 2022/2/7
# __author__ = Ysc

import base64
import json
import os
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA


PEM_DIR = os.path.join('.')


def GeneratePEM():
# rsa算法生成实例
rsa = RSA.generate(1024, Random.new().read)

# Server的秘钥对的生成
private_pem = rsa.exportKey()
with open("%s/server-public.pem" % PEM_DIR, "wb") as f:
f.write(private_pem)

public_pem = rsa.publickey().exportKey()
with open("%s/server-private.pem" % PEM_DIR, "wb") as f:
f.write(public_pem)


class DeEncrypt:
__instance = None
__hasInit = False

def __new__(cls):
if cls.__instance is None:
cls.__instance = object.__new__(cls)
return cls.__instance
else:
return cls.__instance

def __init__(self):
if not self.__hasInit:
with open("%s/server-public.pem" % PEM_DIR) as f:
public_key = f.read()
f.close()
self.public_key = public_key
with open("%s/server-private.pem" % PEM_DIR) as f:
private_key = f.read()
f.close()
self.private_key = private_key

self.__hasInit = True

# todo 长度隐患旧方法
# 使用公钥对内容进行rsa 加密
def Encrypt(self, msg):
key = self.public_key
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
cipher_text = base64.b64encode(cipher.encrypt(msg.encode('utf-8')))
return cipher_text.decode('utf-8')

# 使用私钥对内容进行rsa 解密
def Decrypt(self, msg):
random_generator = Random.new().read
key = self.private_key
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
text = cipher.decrypt(base64.b64decode(msg), random_generator)
return text.decode('utf-8')

AES

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# time : 2022/2/8
# __author__ = Ysc

from Crypto.Cipher import AES
import base64


class AESCipher:

def __init__(self, key: str, iv: str):
if len(key) != 16 or len(iv) != 16:
log.error(f"key or iv 长度异常: {key}, {iv} ")
raise ValueError("length error")

self.key = bytes(key, encoding='utf-8')
self.iv = bytes(iv, encoding='utf-8')

def pkcs7padding(self, text):
"""
明文使用PKCS7填充
最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理
:param text: 待加密内容(明文)
:return:
"""
bs = AES.block_size # 16
length = len(text)
bytes_length = len(bytes(text, encoding='utf-8'))
# tips:utf-8编码时,英文占1个byte,而中文占3个byte
padding_size = length if (bytes_length == length) else bytes_length
padding = bs - padding_size % bs
# tips:chr(padding)看与其它语言的约定,有的会使用'\0'
padding_text = chr(padding) * padding
return text + padding_text

def pkcs7unpadding(self, text):
"""
处理使用PKCS7填充过的数据
:param text: 解密后的字符串
:return:
"""
try:
length = len(text)
unpadding = ord(text[length - 1])
return text[0:length - unpadding]
except Exception as e:
pass

def encrypt(self, content):
"""
AES加密
key,iv使用同一个
模式cbc
填充pkcs7
:param key: 密钥
:param content: 加密内容
:return:
"""
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# 处理明文
content_padding = self.pkcs7padding(content)
# 加密
aes_encode_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
# 重新编码
result = str(base64.b64encode(aes_encode_bytes), encoding='utf-8')
return result

def decrypt(self, content):
"""
AES解密
key,iv使用同一个
模式cbc
去填充pkcs7
:param key:
:param content:
:return:
"""
try:

cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# base64解码
aes_encode_bytes = base64.b64decode(content)
# 解密
aes_decode_bytes = cipher.decrypt(aes_encode_bytes)
# 重新编码
result = str(aes_decode_bytes, encoding='utf-8')
# 去除填充内容
result = self.pkcs7unpadding(result)
except Exception as e:
pass
if result == None:
return ""
else:
return result

  • 本文作者: Ysc Test
  • 本文链接: https://ysctest.cn/posts/67869795.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 法律声明: 本博客提供的所有包括但不限于(文章和API)等服务,仅用于学习,技术分享、交流。不得用于违法犯罪、损害国家利益。非法使用者本站不承担任何法律责任,并且本站保留追究其法律责任的权力!!!