Python接口自动化之通过RSA加解密

2022-03-10 15:40:42 浏览数 (1)

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秘钥算法中, 加密主要用对方的公钥,解密用自己的私钥,签名用自己的私钥,验签用对方的公钥。

0 人点赞