Python3基础使用RSA2(SHA256WithRSA)签名加密作为sign值的问题

接口规范

1、筛选并排序
获取所有请求参数,不包括字节类型参数,如文件、字节流,剔除 sign 字段,剔除值为空的参数,并按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值 ASCII 码递增排序,以此类推
2、拼接
将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用 & 字符连接起来,此时生成的字符串为待签名字符串。

app_id=2021072300007148
request_body={"user_id":1}
timestamp=1612776451123
version=1.0

待签名字符串

app_id=2021072300007148&request_body={"user_id":1}&timestamp=1612776451123&version=1.0

3、调用签名函数

使用各自语言对应的 SHA256WithRSA签名函数利用商户私钥对待签名字符串进行签名,并进行 Base64 编码。

4、生成的签名复制给sign参数

接口Demo

需要插件:pycryptodome

接口文档格式,以下文件在同一个目录下

logo_demo目录 --- config.py   配置文件

logo_demo目录 --- rsa_crypt.py  加密文件

logo_demo目录 --- sign_demo.py  sigh值文件

# coding=utf-8
import json
import time
from base64 import b64decode
from urllib.parse import urlencode

from config import APP_ID, VERSION, APP_PRIVATE_KEY, APP_PUBLIC_KEY, ZAN_PRIVATE_KEY, ZAN_PUBLIC_KEY
from rsa_crypt import RSAPubCrypt, RSAPrvCrypt


def main():
    # 1. 非码签名验签测试
    jump_page = 'https://test-group.51zan.com/into-channel'
    request_body = {
        "notify_url":"http://106.54.78.58:58082/",
        "partner_id": "40000000000000000000",
        "staff_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa24000"
    }

    test_data_dict = {
        "app_id": APP_ID,
        "request_body": json.dumps(request_body, sort_keys=True, separators=(',', ':')),
        "timestamp": int(time.time() * 1000),
        "version": VERSION,
    }
    print("test_data_dict:",test_data_dict)

    # 私钥签名
    rsa_prv_crypt = RSAPrvCrypt(b64decode(APP_PRIVATE_KEY))
    test_data_str = rsa_prv_crypt.sign_data(test_data_dict)
    print("test_data_str:",test_data_str)

    test_data_sign = rsa_prv_crypt.sign(test_data_str)
    print("test_data_sign:",test_data_sign)

    # 公钥验签
    rsa_pub_crypt = RSAPubCrypt(b64decode(APP_PUBLIC_KEY))
    print("公钥验签",rsa_pub_crypt.verify_sign(test_data_str, test_data_sign))  # 成功返回 True 或 失败返回 False

    test_data_dict['sign'] = test_data_sign

    query_string = urlencode(test_data_dict)

    print('{}?{}'.format(jump_page, query_string))
if __name__ == '__main__':
    main()
sign_demo.py
# coding=utf-8
import base64
import json

from Crypto.Cipher import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15


# RSA加密类
class RSACrypt(object):

    def __init__(self, key):
        self.key = RSA.importKey(key)

    @staticmethod
    def sign_data(data_dict):
        tmp = []
        print("data_dict:",data_dict)
        for key in sorted(data_dict.keys()):
            value = data_dict[key]
            # print("value:",value)
            if isinstance(value, dict) or isinstance(value, list):
                tmp.append('{}={}'.format(key, json.dumps(value, sort_keys=True, separators=(',', ':'))))
            else:
                tmp.append('{}={}'.format(key, value))
        # print("tmp",tmp)
        return '&'.join(tmp)


# RSA公钥
class RSAPubCrypt(RSACrypt):

    # RSA公钥加密
    def encrypt(self, data, length=200):
        try:
            # 1024bit的证书用100,2048bit证书用200位
            data = data.encode('utf-8')
            cipher = PKCS1_v1_5.new(self.key)
            res = []
            for i in range(0, len(data), length):
                res.append(cipher.encrypt(data[i:i + length]))
            return str(base64.b64encode(b"".join(res)), encoding='utf-8')
        except:
            return False

    # RSA公钥验证签名
    def verify_sign(self, data, signature):
        try:
            if isinstance(data, dict):
                data = self.sign_data(data)
            data = data.encode('utf-8')
            h = SHA256.new(data)
            pkcs1_15.new(self.key).verify(h, base64.b64decode(signature))
            return True
        except (ValueError, TypeError):
            return False


# RSA私钥
class RSAPrvCrypt(RSACrypt):

    # RSA私钥解密
    def decrypt(self, encrypt_data, length=256):
        # 1024bit的证书用128,2048bit证书用256位
        print("=====")
        try:
            cipher = PKCS1_v1_5.new(self.key)
            encrypt_data = base64.b64decode(encrypt_data)
            data = []
            for i in range(0, len(encrypt_data), length):
                data.append(cipher.decrypt(encrypt_data[i:i + length], 'xyz'))
            return str(b"".join(data), encoding='utf-8')
        except:
            return False

    # RSA私钥生成签名
    def sign(self, data):
        try:
            if isinstance(data, dict):
                data = self.sign_data(data)
            data = data.encode('utf-8')
            h = SHA256.new(data)
            signature = pkcs1_15.new(self.key).sign(h)
            return str(base64.b64encode(signature), encoding='utf-8')
        except:
            return False
rsa_crypt.py
# coding=utf-8

# 公钥
ZAN_PUBLIC_KEY = ('xxx',''sss)

# 私钥
ZAN_PRIVATE_KEY = ('aa','bb')

APP_ID = "20210800007148"  #

VERSION = "1.0"  # 接口版本号,目前固定为1.0

# 测试私钥
APP_PRIVATE_KEY = "MITDDDD"

# 测试公钥
APP_PUBLIC_KEY = " DDDDD"
config.py
原文地址:https://www.cnblogs.com/sugh/p/14499408.html