Hi,大家好。在之前的文章:Python实现各种加密,接口加解密不再难,介绍了Base64、MD5、Sha1、Secret、RSA等几种加密方式,今天结合项目具体介绍RSA加密。
一 RSA算法加密简介
1 介绍
RSA加密算法是一种非对称加密
算法,加密的秘钥是由公钥和私钥两部分组成秘钥对,公钥
用来加密消息,私钥
用来对消息进行解密,公钥是公开的,私钥则是用户自己保留的,由于公钥是公开的,那么任何人只要获取到公钥,都可以使用公钥来加密发送伪造内容。
出于安全性考虑,在发送消息之前我们可以使用RSA
来签名,签名使用私钥来进行签名,使用公钥来进行验签,通过签名我们可以确保用户身份的唯一性,从而提高安全性。
2 加密与签名的关系?
加密和签名都是为了安全性考虑,但略有不同。简单的说,加密
是为了防止信息被泄露,而签名
是为了防止信息被篡改。
(1) 加密
Task 1:Boss要给CoCo发送一条消息,分配保密的工作任务。
RSA的加密过程如下:
1.CoCo生成一对密钥(公钥和私钥),私钥不公开,CoCo自己保留。公钥为公开的,任何人可以获取。
2.CoCo传递自己的公钥给Boss,用CoCo的公钥对消息进行加密。
3.CoCo接收到Boss加密的消息,利用CoCo自己的私钥对消息进行解密。
在这个过程中,只有2次传递过程,第一次是CoCo传递公钥给Boss,第二次是Boss加密消息给CoCo,即使都被敌方截获,也没有危险性,因为只有CoCo的私钥才能对消息进行解密,防止了消息内容的泄露。
(2) 签名
Task 2:CoCo收到Boss发的消息后,需要进行回复“收到”。
RSA签名的过程如下:
1.CoCo生成一对密钥(公钥和私钥),私钥不公开,CoCo自己保留。公钥为公开的,任何人可以获取。
2.CoCo用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给Boss。
3.Boss收到消息后,在获取CoCo的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是CoCo回复的。
在这个过程中,只有2次传递过程,第一次是CoCo传递加签的消息和消息本身给Boss,第二次是Boss获取CoCo的公钥,即使都被敌方截获,也没有危险性,因为只有CoCo的私钥才能对消息进行签名,即使知道了消息内容,也无法伪造带签名的回复给Boss,防止了消息内容的篡改。
综合两个场景会发现,第一个场景虽然被截获的消息没有泄露,但是可以利用截获的公钥,将假指令进行加密,然后传递给CoCo。第二个场景虽然截获的消息不能被篡改,但是消息的内容可以利用公钥验签来获得,并不能防止泄露。
所以在实际应用中,要根据情况使用,也可以同时使用加密和签名,比如CoCo和Boss都有一套自己的公钥和私钥,当CoCo要给Boss发送消息时,先用Boss的公钥对消息加密,再对加密的消息使用CoCo的私钥加签名,达到既不泄露也不被篡改,更能保证消息的安全性。
即:公钥加密、私钥解密、私钥签名、公钥验签。
二 Python实现RSA加解密
接下来我们使用 Python 来实现 RSA 加密与签名,使用的第三方库是Crypto
。
1 生成密钥对
创建RSA密钥,步骤如下:
1、从 Crypto.PublicKey 包中导入 RSA,创建一个密码;
2、生成1024/2048位的RSA 密钥;
3、调用 RSA 密钥实例的 exportKey 方法,传入密码、使用的 PKCS 标准以及加密方案这三个参数;
4、将私钥写入磁盘的文件;
5、使用方法链调用 publickey 和 exportKey 方法生成公钥,写入磁盘上的文件。
示例代码如下:
私钥如下:
公钥如下:
2 公钥加密和私钥解密 (1) 公钥加密
结果如下所示:
代码语言:javascript复制luLmeQPdOIgDLDmCvuIK4QmQg6QXxDhvQ1igNVgURfjij/lNC7bqbWznELaGWy3ZnYWvyJoy2YY8RbjVaYSqwL37/Eta9tR 0/RCcMWK1iXOInAxwHiukvHy3itWhYbu2lQcSljBjoF3/IEEGnh7 MF3MoECIlGVlBR9s6jg5ZU=
(2) 私钥解密
代码语言:javascript复制import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
def decrypt(en_data):
'''
en_data:加密过后的数据,传进来是一个字符串
'''
# base64解码
msg = base64.b64decode(en_data)
# 获取私钥
privatekey = open('private.pem').read()
rsakey = RSA.importKey(privatekey)
# 进行解密
cipher = PKCS1_v1_5.new(rsakey)
data= cipher.decrypt(msg, 'DecryptError')
# 解密出来的是字节码格式,decode转换为字符串
return data.decode()
if __name__ == '__main__':
en_data="luLmeQPdOIgDLDmCvuIK4QmQg6QXxDhvQ1igNVgURfjij/lNC7bqbWznELaGWy3ZnYWvyJoy2YY8RbjVaYSqwL37/Eta9tR 0/RCcMWK1iXOInAxwHiukvHy3itWhYbu2lQcSljBjoF3/IEEGnh7 MF3MoECIlGVlBR9s6jg5ZU="
print(decrypt(en_data))
结果如下所示:
代码语言:javascript复制ITester软件测试小栈
3 私钥签名与公钥验签
(1) 私钥签名
结果如下所示:
代码语言:javascript复制Eb7mtvQGHCuzOR475TPRCR95Qg4GK1Nhbdw2je83JBxPfD0WiZ1Di/vXgQ8eH9fmh5z80epATF0IGT3Lm4DJTgHq apuvhtjYNKv4wnz7c5seTuqWXTEjA6h/PomqW/yMC5/cbPr7w aYEpV 2E NKc/brUS1e6 pN4vHkaOXwM=
(2) 公钥验签
代码语言:javascript复制from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as Sig_pk
from Crypto.PublicKey import RSA
import base64
def verify(data,sign) -> bool:
'''
:param msg: 明文数据,签名之前的数据
:param sign:接收到的sign签名
:return:
'''
# base64解码
data = base64.b64decode(sign)
# 获取公钥
key = open('public.pem').read()
rsakey = RSA.importKey(key)
# 将签名之前的内容进行hash处理
sha_name = SHA.new(sign.encode("utf-8"))
# 验证签名
signer = Sig_pk.new(rsakey)
res= signer.verify(sha_name, sign)
# 验证通过返回True 不通过返回False
return res
if __name__ == '__main__':
# 签名之前的内容
data= "CoCo"
# 签名数据
sign="X3Gg wd7UDh4X8ra PGCyZFUrG 6jDeQt6ajMA0EjwoDwxlddLzYoS4dtjQ2q5WCcRhxcp8fjEyoPXBmJE9rMKDjEIeE/VO0sskbJiO65fU8hgcqdWdgbVqRryhOw Kih I6RIeNRYnOB8GkGD8Qca n9JlOELcxLRdLo3vx6dw="
print(verify(data, sign))
结果如下所示:
代码语言:javascript复制False
三 结合项目实现RSA加解密
需求:接口需要时间戳及token前50位鉴权,通过RSA公钥加密得到签名字符串。
1 RSA封装
rsa封装可在ITester软件测试小栈微信公众号后台回复“rsa
”,进行领取。
2 结合项目实现
(1) 处理鉴权信息
生成token前50位并与时间戳进行拼接:
代码语言:javascript复制from time import time
def generator_sign(token):
# 获取token的前50位
token_50 = token[:50]
# 生成时间戳
timestamp = int(time())
# print(timestamp)
# 接拼token前50位和时间戳
msg = token_50 str(timestamp)
print(msg)
# 进行RSA加密
sign = rsaEncrypt(msg)
return sign,timestamp
(2) 配置请求信息
请求URL与请求头存放在配置文件,以下示例存放在.ini文件:
代码语言:javascript复制[server]
url=http://ITester.com/xxx
auth_type=xxx.itester
(3) 处理请求
发起请求时进行判断,如果auth_type为配置文件指定的类型并且token不为空,则带上加密的鉴权信息。(requests_handler.py 其他代码略)
代码语言:javascript复制 if conf.get("server","auth_type") == "xxx.itester" and token is not None:
from Common.handle_rsa import generator_sign
sign,timestamp = generator_sign(token)
data["sign"] = sign
data["timestamp"] = timestamp
总结:今天主要介绍了RSA加解密,RSA广泛用于加密与解密,还有数字签名通信领域。使用Publick/Private秘钥算法中, 加密
主要用对方的公钥,解密
用自己的私钥,签名
用自己的私钥,验签
用对方的公钥。