每天进步一点点-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-----'''
人生苦短,我用python!