• 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
  • 相关阅读:
    find命令进阶(二):对找到的文件执行操作exec
    find命令进阶用法(一)
    find按照文件大小查找
    find命令查找目录
    什么是ppa
    Linux进程管理命令
    [HDOJ4135]Co-prime
    [HDOJ5391]Zball in Tina Town
    [模拟]位运算实现四则运算
    [HDOJ1233]还是畅通工程
  • 原文地址:https://www.cnblogs.com/sugh/p/14499408.html
Copyright © 2020-2023  润新知