切换主题
Python 签名 & 验签 示例
在 API 请求中,为了确保数据的完整性和安全性,我们使用 RSA 签名 机制来对请求进行加密签名,并在接收方进行验签。
本示例提供了一个 SignatureHandler 类,用于 生成签名 和 验证签名
python
import base64
import json
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.serialization import (
load_pem_private_key,
load_pem_public_key,
)
class SignatureHandler:
def __init__(self, key: str, key_type: str = "private"):
"""
初始化签名/验签类
:param key: 私钥或公钥内容(无头尾)
:param key_type: 键类型,"private" 表示私钥,"public" 表示公钥
"""
if key_type == "private":
pem_key = (
"-----BEGIN PRIVATE KEY-----\n"
+ "\n".join(key[i:i + 64] for i in range(0, len(key), 64))
+ "\n-----END PRIVATE KEY-----"
)
self.key = load_pem_private_key(pem_key.encode(), password=None)
self.is_private = True
elif key_type == "public":
pem_key = (
"-----BEGIN PUBLIC KEY-----\n"
+ "\n".join(key[i:i + 64] for i in range(0, len(key), 64))
+ "\n-----END PUBLIC KEY-----"
)
self.key = load_pem_public_key(pem_key.encode())
self.is_private = False
else:
raise ValueError("Invalid key_type. Must be 'private' or 'public'.")
def generate_signature(self, merchant_id: str, timestamp: str, timezone: str, body: dict) -> str:
"""
生成签名
:param merchant_id: 商户 ID
:param timestamp: 时间戳
:param timezone: 时区
:param body: 请求体字符串
:return: 生成的签名(Base64 编码后的字符串)
"""
if not self.is_private:
raise ValueError("Key must be private to generate signature.")
# 拼接签名内容
body_str = json.dumps(body, separators=(",", ":"), ensure_ascii=False)
# 拼接签名内容
sign_content = f"{merchant_id}.{timestamp}.{timezone}.{body_str}"
# 生成签名
signature = self.key.sign(
sign_content.encode(),
padding.PKCS1v15(),
hashes.SHA256(),
)
# 返回 Base64 编码的签名字符串
return base64.b64encode(signature).decode()
def verify_signature(self, merchant_id: str, timestamp: str, timezone: str, body: dict,
received_signature: str) -> bool:
"""
验签方法
:param merchant_id: 商户 ID
:param timestamp: 时间戳
:param timezone: 时区
:param body: 请求体字符串
:param received_signature: 客户端发送的签名(Base64 编码后的字符串)
:return: 验签结果,True 为成功,False 为失败
"""
if self.is_private:
raise ValueError("Key must be public to verify signature.")
body_str = json.dumps(body, separators=(",", ":"), ensure_ascii=False)
# 拼接签名内容
sign_content = f"{merchant_id}.{timestamp}.{timezone}.{body_str}"
try:
# 对收到的签名进行解码
decoded_signature = base64.b64decode(received_signature)
# 验证签名
self.key.verify(
decoded_signature,
sign_content.encode(),
padding.PKCS1v15(),
hashes.SHA256(),
)
return True
except Exception as e:
return False