继上篇对 RSA 公钥模数和指数的学习,这次我们针对实际应用中 RSA 加密/解密,签名/验签 的使用,利用 Python 进行具体实现。经过查询整理,发现有三种实现方法,下面我们一一展示。
一、rsa 包的实现
首先需要安装 rsa,pip install rsa
import rsa
import base64
def rsaEncrypt(content, pubkey):
'''
对字符串进行公钥加密
:param content: 被加密的字符串
:return: 加密后的内容
'''
# content = content.encode('utf-8')#明文编码格式
result = rsa.encrypt(content.encode(), pubkey)
return result
def rsaDecrypt(result, privkey):
'''
利用rsa包进行私钥解密
:param result: 被加密的内容
:param privkey: 私钥
:return: 解密后的内容
'''
result = base64.b64decode(result)
print(result)
content = rsa.decrypt(result, privkey).decode()
# content = content.decode('utf-8')
return content
if __name__ == '__main__':
############ 使用公钥 - 私钥对信息进行"加密" + "解密" ##############
message = 'acorn'
#利用rsa包生成公钥、私钥,
(pubkey, privkey) = rsa.newkeys(1024)
print(pubkey, privkey)
print(pubkey.save_pkcs1())
# filename = 'public.pem'
# save(pubkey, filename)
result = rsaEncrypt(message, pubkey)
result = base64.b64encode(result)
print('加密后的密文为:{}'.format(result))
content = rsaDecrypt(result, privkey)
print('解密后的明文为:{}'.format(content))
############ 使用私钥 - 公钥对信息进行"签名" + "验签" ##############
#明文
mss = '重要指令'
#私钥签名
signature = rsa.sign(mss.encode(), privkey, 'SHA-1')
print(signature)
#根据收到的明文、密文,然后用公钥验证,进行身份确认
rsa.verify(mss.encode(), signature, pubkey)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
二、Crypto 包的实现
pycrypto,pycrytodome 和 crypto 是一个东西,crypto 在 python 上面的名字是 pycrypto 它是一个第三方库,但是已经停止更新,所以不建议安装这个库;
windows 下 python3.6 版本以上安装比较麻烦(本人是 Python3.7,尝试安装未成功,如果需要尝试安装的,可以参考点击这里),在安装无果的情况下,可以安装 pycryptodome,它是pycrypto 的延伸版本,用法和 pycrypto 是一模一样的;
pip install pycryptodome1
安装完成后,在 Python 各种引用包存放路径下,把文件夹 crypto 改为 Crypto 即可。
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 #用于加密
import base64
import Crypto.Signature.PKCS1_v1_5 as sign_PKCS1_v1_5 #用于签名/验签
from Crypto import Hash
def generate_rsa_keys():
random_generator = Random.new().read
key = RSA.generate(1024, random_generator) #使用伪随机数来辅助生成
# key = RSA.generate(1024)
pubkey = key.publickey().export_key('PEM') #默认是 PEM的
privkey = key.export_key('PEM')
return pubkey, privkey
def rsaEncrypt(message, pubkey):
'''
RSA加密
:param message: 被加密的字符串
:param pubkey: 公钥
:return:
'''
rsakey = RSA.import_key(pubkey)
cipher = PKCS1_v1_5.new(rsakey)
cipher_text = base64.b64encode(cipher.encrypt(message.encode()))
print(cipher_text)
return cipher_text
def rsaDecrypt(result, privkey):
'''
私钥解密
:param result:
:param privkey:
:return:
'''
result = base64.b64decode(result)
rsakey = RSA.import_key(privkey)
cipher = PKCS1_v1_5.new(rsakey)
content = cipher.decrypt(result, Random.new().read).decode()
print(content)
def save(key, filename):
# 保存密钥
with open(filename, 'w+') as f:
f.write(key)
def read(filename):
# 导入密钥
with open(filename, 'rb') as f:
key = f.read()
return key
def skey_to_pkey(privkey):
'''
已知私钥的情况下,生成公钥
:param privkey:
:return:
'''
s_key = RSA.import_key(privkey)
p_key = s_key.publickey().export_key()
return p_key
def sign_with_privkey(message, privkey):
'''
私钥签名
:param message:明文
:param privkey:
:return:密文
'''
signer = sign_PKCS1_v1_5.new(RSA.import_key(privkey))
rand_hash = Hash.SHA256.new()
rand_hash.update(message.encode())
signature = signer.sign(rand_hash)
return signature
def verify_with_pubkey(signature, message, pubkey):
'''
公钥验签
:param signature:密文
:param message:明文
:param pubkey:公钥
:return:
'''
verifier = sign_PKCS1_v1_5.new(RSA.import_key(pubkey))
rand_hash = Hash.SHA256.new()
rand_hash.update(message.encode())
verify = verifier.verify(rand_hash, signature)
return verify
def execute_without_signature(pubkey, privkey):
'''
公钥加密,私钥解密
:param pubkey:
:param privkey:
:return:
'''
message = 'acorn'
result = rsaEncrypt(message, pubkey)
rsaDecrypt(result, privkey)
print("rsa test success!")
def execute_with_signature(pubkey, privkey):
'''
签名验证,不加密
:param pubkey:
:param privkey:
:return:
'''
text = 'herish'
assert verify_with_pubkey(sign_with_privkey(text,privkey), text, pubkey)
print("rsa Signature verified!")
if __name__ == '__main__':
pubkey, privkey = generate_rsa_keys()
print(pubkey, privkey)
############ 使用公钥 - 私钥对信息进行"加密" + "解密" ##############
execute_without_signature(pubkey, privkey)
############ 使用私钥 - 公钥对信息进行"签名" + "验签" ##############
execute_with_signature(pubkey, privkey)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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
三、cryptography 包的实现
首先安装 cryptography,pip install cryptography
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa,padding
from cryptography.hazmat.primitives import serialization,hashes
from cryptography.hazmat.primitives.serialization import NoEncryption,\
Encoding, PrivateFormat, PublicFormat
import base64
from cryptography.exceptions import InvalidSignature
ALGORITHM_DICT = {
'sha1': hashes.SHA1(),
'sha224': hashes.SHA224(),
'sha256': hashes.SHA256(),
'sha384': hashes.SHA384(),
'sha512': hashes.SHA512()
}
def generate_keys():
'''
生成公钥和私钥
:return:
'''
privkey = rsa.generate_private_key(
public_exponent=65537,
key_size=1024,
backend=default_backend(),
)
new_privkey = privkey.private_bytes(
Encoding.PEM,
PrivateFormat.PKCS8,
NoEncryption()
)
pubkey = privkey.public_key()
new_pubkey = pubkey.public_bytes(
Encoding.PEM,
PublicFormat.SubjectPublicKeyInfo,
)
print(new_pubkey, new_privkey)
return pubkey, privkey
def rsaEncrypt(message, pubkey, algorithm='sha1'):
'''
公钥加密
:param message:
:param pubkey:
:param algorithm:密码散列函数算法
:return:
'''
if not isinstance(message, bytes):
message = message.encode()
algorithm = ALGORITHM_DICT.get(algorithm)
padding_data = padding.OAEP(
mgf=padding.MGF1(algorithm=algorithm),
algorithm=algorithm,
label=None
)
ciphertext = pubkey.encrypt(message, padding_data)
ciphertext = base64.b64encode(ciphertext)
print(ciphertext)
return ciphertext
def rsaDecrypt(result, privkey, algorithm='sha1'):
'''
私钥解密
:param result:加密后的内容
:param privkey:
:param algorithm:密码散列函数算法
:return:
'''
algorithm = ALGORITHM_DICT.get(algorithm)
padding_data = padding.OAEP(
mgf=padding.MGF1(algorithm=algorithm),
algorithm=algorithm,
label=None
)
result = base64.b64decode(result)
content = privkey.decrypt(result, padding_data).decode()
print(content)
return content
def execute_without_signature(pubkey, privkey):
#公钥加密,私钥解密
message = 'herish'
ciphertext = rsaEncrypt(message, pubkey, 'sha256')
content = rsaDecrypt(ciphertext, privkey, 'sha256')
print("rsa test success!")
def sign(message, privkey, algorithm='sha1'):
'''
私钥签名
:param message:
:param privkey:
:param algorithm:
:return:
'''
if not isinstance(message, bytes):
message = message.encode()
algorithm = ALGORITHM_DICT.get(algorithm)
padding_data = padding.PSS(
mgf=padding.MGF1(algorithm),
salt_length=padding.PSS.MAX_LENGTH
)
return privkey.sign(message, padding_data, algorithm)
def verify(message, signature, pubkey, padding_mode='pss', algorithm='sha1'):
'''
公钥验签
:param message:
:param signature:
:param pubkey:
:param padding_mode:
:param algorithm:
:return:
'''
if not isinstance(message, bytes):
message = message.encode()
algorithm = ALGORITHM_DICT.get(algorithm)
if padding_mode == 'pkcs1':
padding_data = padding.PKCS1v15()
else:
padding_data = padding.PSS(
mgf=padding.MGF1(algorithm),
salt_length=padding.PSS.MAX_LENGTH
)
try:
pubkey.verify(signature, message,
padding_data, algorithm)
except InvalidSignature:
padd_verify = False
else:
padd_verify = True
return padd_verify
def execute_with_signature(pubkey, privkey):
text = 'herish'
signature = sign(text, privkey, 'sha256')
assert verify(message=text, signature=signature, pubkey=pubkey, algorithm='sha256')
print("rsa Signature verified!")
if __name__ == '__main__':
pubkey, privkey = generate_keys()
############ 使用公钥 - 私钥对信息进行"加密" + "解密" ##############
# execute_without_signature(pubkey, privkey)
############ 使用私钥 - 公钥对信息进行"签名" + "验签" ##############
execute_with_signature(pubkey, privkey)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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164