"""
AsymmetricEncryption类可以做这些
生成私钥公钥对
非对称加密/解密/签名/验签名
记得运行这个
pip install pycryptodome
以安装所需的包
"""
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
class AsymmetricEncryption:
def __init__(self, path_private='private_key.pem', path_public='public_key.pem'):
self.path_private = path_private
self.path_public = path_public
def get_key(self, key='private'):
if key == 'private':
path = self.path_private
elif key == 'public':
path = self.path_public
else:
return False
with open(path, "rb") as file_obj:
data = file_obj.read()
key = RSA.import_key(data)
return key
def get_private_key(self):
key_private = self.get_key('private')
return key_private
def get_public_key(self):
key_public = self.get_key('public')
return key_public
def generate(self, ):
"""
这个方法可以生成一对私钥/公钥
"""
key_obj = RSA.generate(2048)
with open(self.path_private, 'wb') as private_file_obj:
private_key = key_obj.export_key()
private_file_obj.write(private_key)
with open(self.path_public, 'wb') as public_file_obj:
public_key = key_obj.publickey().export_key()
public_file_obj.write(public_key)
return True
def encrypt(self, data):
"""
这个方法可以把data进行加密
data是byte类型
加密后的数据也是byte类型
"""
public_key = self.get_public_key()
crypt_obj = PKCS1_OAEP.new(public_key)
encrypted_data = crypt_obj.encrypt(data)
return encrypted_data
def decrypt(self, data):
"""
这个方法可以把data进行解密
data是byte类型
解密后的数据也是byte类型
"""
private_key = self.get_private_key()
crypt_obj = PKCS1_OAEP.new(private_key)
data_decrypted = crypt_obj.decrypt(data)
return data_decrypted
def signature(self, data):
"""
这个方法可以对data进行签名
data是byte类型
签名也是byte类型
"""
digest = SHA256.new(data)
private_key = self.get_private_key()
sign_obj = pkcs1_15.new(private_key)
# noinspection PyTypeChecker
sign = sign_obj.sign(digest)
return sign
def verify(self, data, sign):
"""
这个方法可以对data进行验签
data是byte类型数据
sign是byte类型签名
结果是bool类型
"""
digest = SHA256.new(data)
public_key = self.get_public_key()
try:
sign_obj = pkcs1_15.new(public_key)
# noinspection PyTypeChecker
sign_obj.verify(digest, sign)
return True
except ValueError:
return False
@staticmethod
def help(file_out=False):
"""
这个方法提供非加密算法相关知识
如果希望把文档输出到txt文件,设置参数file_out=True
"""
info = """
RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。
这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。
是由一对密钥来进行加解密的过程,分别称为公钥和私钥。
两者之间有数学相关,该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。
通常个人保存私钥,公钥是公开的(可能同时多人持有)。
RSA加密、签名区别
加密和签名都是为了安全性考虑,但略有不同。
常有人问加密和签名是用私钥还是公钥?
其实都是对加密和签名的作用有所混淆。
简单的说,加密是为了防止信息被泄露,而签名是为了防止信息被篡改。
这里举2个例子说明。
第一个场景:战场上,B要给A传递一条消息,内容为某一指令。
RSA的加密过程如下:
(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。
(2)A传递自己的公钥给B,B用A的公钥对消息进行加密。
(3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。
在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,
即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露。
第二个场景:A收到B发的消息后,需要进行回复“收到”。
RSA签名的过程如下:
(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。
(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。
(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。
在这个过程中,只有2次传递过程,第一次是A传递加签的消息和消息本身给B,第二次是B获取A的公钥,
即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行签名,即使知道了消息内容,
也无法伪造带签名的回复给B,防止了消息内容的篡改。
但是,综合两个场景你会发现,第一个场景虽然被截获的消息没有泄露,但是可以利用截获的公钥,将假指令进行加密,然后传递给A。
第二个场景虽然截获的消息不能被篡改,但是消息的内容可以利用公钥验签来获得,并不能防止泄露。
所以在实际应用中,要根据情况使用,也可以同时使用加密和签名。
比如A和B都有一套自己的公钥和私钥,当A要给B发送消息时,先用B的公钥对消息加密,再对加密的消息使用A的私钥加签名,
达到既不泄露也不被篡改,更能保证消息的安全性。
总结:公钥加密、私钥解密、私钥签名、公钥验签
文档摘抄于简书PC君 这是链接 https://www.cnblogs.com/pcheng/p/9629621.html
"""
print(info)
if file_out:
with open('RSA加密-解密-签名-验签的原理及方法.txt', 'w') as file_obj:
file_obj.write(info)
# 用法演示
def main():
# 实例化,也可以传入私钥公钥的路径,其他方法加密等操作都是基于私钥公钥文件
# sra_obj = AsymmetricEncryption(path_private='xx/private_xx.pem', path_public='yy/public_name.pem')
sra_obj = AsymmetricEncryption()
# 如果私钥公钥路径还没有公钥私钥对应文件,可以运行这个方法生成私钥公钥对文件
sra_obj.generate()
# 对数据进行加密,传入的数据必须是byte类型
# 字符串可以通过这个方法转化成byte类型: data='123456'.encode('utf8') 有时候你需要使用gbk字符集进行编码
data = b'123456'
result = sra_obj.encrypt(data)
print(result) # b'cv\x8c\xd8\x......' <---这是加密后的数据,没有私钥就算神仙来也破解不了
# 对数据进行解密,传入的数据必须是byte类型
data = sra_obj.decrypt(result)
print(data) # b'123456'
# 对数据进行签名,传入的数据必须是byte类型
sign = sra_obj.signature(data)
print(sign) # b'\x13\x9d\xe......'
# 对数据进行验签
state = sra_obj.verify(data, sign)
print(state) # True
state = sra_obj.verify(b'456789', sign) # 这行是一个反例
print(state) # False 这次内容和签名不一致,所以验签结果是失败的
main()