修复了沙箱私钥解析问题

This commit is contained in:
2026-07-09 01:58:38 +08:00
parent 9c11698660
commit d7d38d9b08

View File

@@ -48,31 +48,80 @@ def get_alipay_config(club_id=None):
# ==================== 密钥加载 ====================
def _load_private_key(key_str):
"""加载 RSA 私钥,兼容 PEM 格式与裸 Base64DER格式。"""
"""加载 RSA 私钥,兼容 PEM、PKCS#8 DER、PKCS#1、PKCS#8 多种格式。
沙箱私钥常为 PKCS#1 格式(裸 base64 前缀 MIIEowIBAAKCAQEA
生产私钥常为 PKCS#8 格式(裸 base64 前缀 MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcw
此处按顺序尝试多种加载方式以兼容两者。
"""
if isinstance(key_str, bytes):
key_str = key_str.decode('utf-8')
key_str = key_str.strip()
# 1. 标准 PEM含 -----BEGIN 头)
if '-----BEGIN' in key_str:
return serialization.load_pem_private_key(
key_str.encode('utf-8'), password=None,
)
der_bytes = base64.b64decode(key_str)
return serialization.load_der_private_key(der_bytes, password=None)
raw = key_str.replace('\n', '').replace('\r', '').replace(' ', '')
# 2. PKCS#8 DER裸 base64
try:
der_bytes = base64.b64decode(raw)
return serialization.load_der_private_key(der_bytes, password=None)
except Exception:
pass
# 3. PKCS#1 PEM 包装(-----BEGIN RSA PRIVATE KEY-----
pem_pkcs1 = _wrap_pem(raw, 'RSA PRIVATE KEY')
try:
return serialization.load_pem_private_key(pem_pkcs1.encode('utf-8'), password=None)
except Exception:
pass
# 4. PKCS#8 PEM 包装(-----BEGIN PRIVATE KEY-----
pem_pkcs8 = _wrap_pem(raw, 'PRIVATE KEY')
return serialization.load_pem_private_key(pem_pkcs8.encode('utf-8'), password=None)
def _load_public_key(key_str):
"""加载支付宝公钥,兼容 PEM 格式与裸 Base64DER格式。"""
"""加载支付宝公钥,兼容 PEM、X.509 DER 及 PEM 包装格式。
支付宝公钥标准为 X.509 SubjectPublicKeyInfo裸 base64 前缀通常为
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8Aload_der_public_key 原生支持;
为稳妥起见追加 PEM 包装兜底。
"""
if not key_str:
return None
if isinstance(key_str, bytes):
key_str = key_str.decode('utf-8')
key_str = key_str.strip()
# 1. 标准 PEM含 -----BEGIN 头)
if '-----BEGIN' in key_str:
return serialization.load_pem_public_key(key_str.encode('utf-8'))
der_bytes = base64.b64decode(key_str)
return serialization.load_der_public_key(der_bytes)
raw = key_str.replace('\n', '').replace('\r', '').replace(' ', '')
# 2. X.509 DER裸 base64
try:
der_bytes = base64.b64decode(raw)
return serialization.load_der_public_key(der_bytes)
except Exception:
pass
# 3. PEM 包装兜底(-----BEGIN PUBLIC KEY-----
pem_pub = _wrap_pem(raw, 'PUBLIC KEY')
return serialization.load_pem_public_key(pem_pub.encode('utf-8'))
def _wrap_pem(raw_b64, label):
"""将裸 base64 字符串包装为标准 PEM 格式(每行 64 字符)。"""
lines = [raw_b64[i:i + 64] for i in range(0, len(raw_b64), 64)]
return f'-----BEGIN {label}-----\n' + '\n'.join(lines) + f'\n-----END {label}-----'
# ==================== 签名 / 验签 ====================