Python3.6.1 RSA 公钥pubkey分段加密

前段时间,遇到有接口是使用rsa公钥加密方法实现的,于是需要编写rsa 加密的脚本。其中 ,公钥(publickey)是已知的。不同长度的字段使用RSA加密出来的长度不一样。
加密的字段长短规则如下:
加密的 plaintext 最大长度是 证书key位数/8 - 11, 例如1024 bit的证书,被加密的串最长 1024/8 - 11=117,
那么对于 2048bit的证书,被加密的长度最长2048/8 - 11 =245,
解决办法是 分块 加密,然后分块解密就行了,
因为 证书key固定的情况下,加密出来的串长度是固定的。
也就是说,如果使用2048bit的证书,并且被加密的字符段是小于245个,那么被加密出来的字符长度是344个,以此类推,被加密的字符串可以是688个,1032个等。

以下是针对某个接口的传参使用rsa加密技术后,对该接口进行的测试,脚本如下:

#coding=utf-8
import re
import json
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
import base64
import requests
from base64 import b64encode, b64decode
import rsa

#单次加密串的长度最大为 (key_size/8)-11
'''
加密的 plaintext 最大长度是 证书key位数/8 - 11, 例如1024 bit的证书,被加密的串最长 1024/8 - 11=117, 
那么对于 2048bit的证书,被加密的长度最长2048/8 - 11 =245,
解决办法是 分块 加密,然后分块解密就行了,
因为 证书key固定的情况下,加密出来的串长度是固定的。
'''
def rsa_encrypt(msg,pubkey):
    pub_title=pubkey
    pubkey_str="""-----BEGIN PUBLIC KEY-----""" + '\n' + pub_title + '\n' + """-----END PUBLIC KEY-----"""
    msg = msg.encode(encoding="utf-8")
    length = len(msg)
    default_length = 245
    # 公钥加密
    pubobj = Cipher_pkcs1_v1_5.new(RSA.importKey(pubkey_str))
    # 长度不用分段
    if length < default_length:
        encry_text = base64.b64encode(pubobj.encrypt(msg))  # 通过生成的对象加密message明 # 对传递进来的用户名或密码字符串
        encry_value = encry_text.decode('utf8')
        return encry_value
    # 需要分段
    offset = 0
    res = []
    while length - offset > 0:
        if length - offset > default_length:
            res.append(base64.b64encode(pubobj.encrypt(msg[offset:offset + default_length])).decode("utf-8"))
        else:
            res.append(base64.b64encode(pubobj.encrypt(msg[offset:])).decode("utf-8"))
        offset += default_length
    return "".join(res)

if __name__ == '__main__':
    pubkey='MIIBIjANBgkqeriG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxq+EkcWV+gB/B81dqK+WJM1/0qgCS0uFodLv/uygtNTKf4mbHwfy/90SPILkpqkO31F3B5MYyLkl9MQFuA9DD95fcFOQFL7wEUnAtnGbzRbVCqo2JcUpyWV79LDeFlsL87NMvwtIGf5geEDLLPT7WS63X6o3LAaWrro3Z/rzf6zwKSWnzoMhjcrV6inwwkLGpOMQxwOgteaLmYvJ8x3BayokTGRDOH2JMMw49C9c5S2mwJ+axkAdi0ei83Y5K5WcCEbxeNaxZiDZs9HN428/QJtOtcXPtp0PyUH3449ycwBjYF+HHjxihvs/PzI/agPWVtE4hGba1Ldya5JMGh7KKQIDAQAB'
    login_url = 'http://xx.yy.zz.com/api/user/type'
    login_data = {"loginName": "[email protected]", "password": "1234test", "loginType": "email", "key": "123445678dfghj"}
    headers_1 = {'Referer': 'http://xx.yy.zz.com', 'Content-Type': 'application/json'}
    r = requests.post(url=login_url, data=json.dumps(login_data), headers=headers_1)
    json_data = json.loads(r.text)
    #print("登录的结果返回值是:\n", json_data)
    token = json_data['data']['token']
    #print("登录的token是:\n", token)
    headers_2 = {'Referer': 'http://xx.yy.zz.com',
                 'Content-Type': 'application/json',
                 'x-Api-token': token}
    msg='{"newPwd": "1234abcd", "origin": "abcd1234", "verified": "1234abcd"}'
    print("未加密前的接口数据是:\n",msg)
    test_data=rsa_encrypt(msg,pubkey)
    print("接口测试传参结果是:\n",test_data)
    test_url_pwd='http://xx.yy.zz.com/api/user/pwd/modify'
    test_r=requests.post(url=test_url_pwd,data=test_data,headers=headers_2)
    test_json_data=json.loads(test_r.text)
    print("接口测试结果是:\n",test_json_data)

运行出来结果如下:

未加密前的接口数据是:
 {"newPwd": "1234abcd", "origin": "abcd1234", "verified": "1234abcd"}
接口测试传参结果是:
 OLMy+O4To088reveyvIv3efWTG164BQvjWivZTTeBalEHbqbZ/3kWGXqpZPDrm8+N4+8utk13/wxiipmiPny5xBxbI+CuVssv+gN8owbsqJTlLDgRb0ZhpWbF83cUDVp9/O11epZKXslhsSjINqxRKLqKMYqXd9tZK37KKxbhiZjEu6RVlyUkrri3i1jGJO/e4bmeHIv/XnrEV3J5g2MMv0HvmzKBfpRaGuTYpjAE64u1X7djRxApP+XA/wqSjf13ggPB4hxAmdnV/beNSyg77NVK6gDPvVi7X4zhZ6mjqoZSmA2if/QD5zL8izfHfi7YRqgVW/Kp74URZMzW0HuAA==
接口测试结果是:
 {'code': 'm00000', 'result': True}

注意:对于指定的pubkey唯一,每次被加密的字符串唯一,但是使用RSA 加密后出来的字符串都是不同的,因为 Cipher_pkcs1_v1_5.new(RSA.importKey(pubkey_str))获取得到的值是随机的,只要满足解密出来的字符串是被加密前的字符串即可。

参考:
http://blog.csdn.net/orangleliu/article/details/72964948

猜你喜欢

转载自blog.csdn.net/liujingqiu/article/details/79290271