修复了沙箱私钥解析问题
This commit is contained in:
@@ -48,31 +48,80 @@ def get_alipay_config(club_id=None):
|
||||
# ==================== 密钥加载 ====================
|
||||
|
||||
def _load_private_key(key_str):
|
||||
"""加载 RSA 私钥,兼容 PEM 格式与裸 Base64(DER)格式。"""
|
||||
"""加载 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 格式与裸 Base64(DER)格式。"""
|
||||
"""加载支付宝公钥,兼容 PEM、X.509 DER 及 PEM 包装格式。
|
||||
|
||||
支付宝公钥标准为 X.509 SubjectPublicKeyInfo,裸 base64 前缀通常为
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A,load_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}-----'
|
||||
|
||||
|
||||
# ==================== 签名 / 验签 ====================
|
||||
|
||||
Reference in New Issue
Block a user