继上篇对 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)
二、Crypto 包的实现
pycrypto,pycrytodome 和 crypto 是一个东西,crypto 在 python 上面的名字是 pycrypto 它是一个第三方库,但是已经停止更新,所以不建议安装这个库;
windows 下 python3.6 版本以上安装比较麻烦(本人是 Python3.7,尝试安装未成功,如果需要尝试安装的,可以参考点击这里),在安装无果的情况下,可以安装 pycryptodome,它是pycrypto 的延伸版本,用法和 pycrypto 是一模一样的;
pip install pycryptodome
安装完成后,在 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)
三、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)