每天进步一点点-python如何进行签名及验签

生成签名

# python3

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:SunXiuWen
# datetime:2021/10/19 0019
import rsa
import base64
from urllib import parse

from config import PRIVATE_KEY


def check_string(method, path, params):
    """
    :param method 请求方法  get、post、put
    :param params 请求参数 {key:value}
    :param path 请求资源地址  /query/info
    整理请求方式,路径及请求参数字符串
    :return:
    """
    # 1.将请求的资源地址进行url编码
    str_encode_head = parse.quote(path, 'utf-8')
    # 2.请求参数按key升序排序
    keys = sorted(params.keys())
    # 3.排序后的参数(key=value)用&拼接起来
    sing_str = ''
    for key in keys:
        sing_str += str(key) + '=' + str(params[key]) + '&'
    sign_str = sing_str[:-1]
    # 4.进行URL编码
    # str_encode_param = request.quote(sign_str)
    str_encode_param = parse.quote(sign_str)
    # 将HTTP请求方式、url、url编码的参数拼接
    str_in_sign = method.upper() + '&' + str_encode_head + '&' + str_encode_param
    # logger.debug("验签前的串:%s" % StrInSign)
    return str_in_sign


# 生成签名
def create_sign_for_private(http_method: str, url_path, params):
    """由私钥生成的签名"""
    # 按规则生成签名字符串
    message = check_string(http_method, url_path, params)
    print(f"根据规则生成签名前的字符串为:{message}")

    # 加载私钥
    private_key = rsa.PrivateKey.load_pkcs1(PRIVATE_KEY)
    print(f"加载私钥对象:{private_key}")

    # 生产签名串
    signature = rsa.sign(message.encode('utf-8'), private_key, 'SHA-256')
    print(f"rsa算法生成签名串:{signature}")

    # 加密后进行base64编码
    sign = base64.b64encode(signature)
    print(f"对生成的签名进行base64编码:{sign}")
    return sign


if __name__ == '__main__':
    # 测试生成签名
    params3 = {'orderId': '83621102010000410439',
               'orderStatus': '10702',
               'operation': 'P216040401'}
    create_sign_for_private("get", '/order/status/up', params3)

#对生成的签名进行base64编码:b'dzzvEjiT2gqyC3LWdmKw9ICwfh8eht4lbzOk0heIdfPkVTTzFC3cFIg/1GcQEeIVub1Pth1IxSkfXzCx490TgapDLZTdiMBXK31uaMoNC66vIVhv6UDq7bbRnTGVUixnP7HvfL0DXykyJVAW53I01TZVD8pjJdO9mgYAsr6721U='

验签

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:SunXiuWen
# datetime:2021/10/20 0020
"""pip install pycryptodome  py3.7"""
import base64
import traceback
from urllib import parse
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from config import PUBLIC_KEY


def check_string(method, path, params):
    """
    :param method 请求方法  get、post、put
    :param params 请求参数 {key:value}
    :param path 请求资源地址  /query/info
    整理请求方式,路径及请求参数字符串
    :return:
    """
    # 1.将请求的资源地址进行url编码
    str_encode_head = parse.quote(path, 'utf-8')
    # 2.请求参数按key升序排序
    keys = sorted(params.keys())
    # 3.排序后的参数(key=value)用&拼接起来
    sing_str = ''
    for key in keys:
        sing_str += str(key) + '=' + str(params[key]) + '&'
    sign_str = sing_str[:-1]
    # 4.进行URL编码
    # str_encode_param = request.quote(sign_str)
    str_encode_param = parse.quote(sign_str)
    # 将HTTP请求方式、url、url编码的参数拼接
    str_in_sign = method.upper() + '&' + str_encode_head + '&' + str_encode_param
    # logger.debug("验签前的串:%s" % StrInSign)
    return str_in_sign


# 验签
def signature_verification(http_method: str, url_path: str, params: dict, sign):
    flag = False
    try:
        # 1.对请求按签名规则生成签名前的字符串
        message_before = check_string(http_method, url_path, params)
        # 2. 对签名源串进行sha256计算,生成sha256摘要
        sha256_obj = SHA256.new()
        sha256_obj.update(message_before.encode('utf-8'))
        sha256_obj.digest()
        # 3. 对源签名进行BASE64解编码
        decode_sign = base64.decodebytes(sign.encode('utf-8'))
        # 4. 使用RSA的公钥对签名进行验证
        public_key = RSA.importKey(PUBLIC_KEY)
        verifier = PKCS1_v1_5.new(public_key)
        flag = verifier.verify(sha256_obj, decode_sign)
        print(f"验签结果为:{flag},\n入参:{params}")
    except Exception as e:
        print(f"验签异常:{e}\n{traceback.format_exc()}")
    finally:
        return flag


if __name__ == '__main__':
    data = {'orderId': '83621102010000410439',
            'orderStatus': '10702',
            'operation': 'P216040401'}

    # 生成签名
    from python3生成签名 import create_sign_for_private

    sign = create_sign_for_private("get", '/order/status/up', data)
    sign_string = sign.decode("utf-8")

    # 验签
    ret = signature_verification("get", "/order/status/up", data, sign_string)
    print(ret)

密钥配置

# config.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:SunXiuWen
# datetime:2021/12/29 0029

PUBLIC_KEY = '''-----BEGIN PUBLIC KEY-----
                   xxxxx
                    -----END PUBLIC KEY-----'''
PRIVATE_KEY = '''-----BEGIN RSA PRIVATE KEY-----
                    yyyyy
                    -----END RSA PRIVATE KEY-----'''

posted @ 2022-08-02 10:17  Alive_2020  阅读(1251)  评论(0编辑  收藏  举报