diff --git a/backend/app/__pycache__/alipay_provider.cpython-313.pyc b/backend/app/__pycache__/alipay_provider.cpython-313.pyc index 9856ee0..cf66842 100644 Binary files a/backend/app/__pycache__/alipay_provider.cpython-313.pyc and b/backend/app/__pycache__/alipay_provider.cpython-313.pyc differ diff --git a/backend/app/alipay_provider.py b/backend/app/alipay_provider.py index b3fa2d8..4e4f23a 100644 --- a/backend/app/alipay_provider.py +++ b/backend/app/alipay_provider.py @@ -139,7 +139,11 @@ def _certificate_public_key(certificate) -> str: raise AlipayTransferError("支付宝证书必须包含 RSA 公钥") return key.public_bytes( encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.PKCS1, + # alipay-sdk-python's verify_with_rsa uses + # rsa.PublicKey.load_pkcs1_openssl_pem(), which expects an X.509 + # SubjectPublicKeyInfo (BEGIN PUBLIC KEY), not PKCS#1's + # BEGIN RSA PUBLIC KEY structure. + format=serialization.PublicFormat.SubjectPublicKeyInfo, ).decode("ascii") diff --git a/backend/tests/__pycache__/test_alipay_provider.cpython-313-pytest-9.1.1.pyc b/backend/tests/__pycache__/test_alipay_provider.cpython-313-pytest-9.1.1.pyc index b6a2933..ce58eed 100644 Binary files a/backend/tests/__pycache__/test_alipay_provider.cpython-313-pytest-9.1.1.pyc and b/backend/tests/__pycache__/test_alipay_provider.cpython-313-pytest-9.1.1.pyc differ diff --git a/backend/tests/test_alipay_provider.py b/backend/tests/test_alipay_provider.py index 6aebb0a..e11e54b 100644 --- a/backend/tests/test_alipay_provider.py +++ b/backend/tests/test_alipay_provider.py @@ -230,6 +230,23 @@ def test_root_certificate_serial_ignores_non_rsa_certificates(): assert alipay_provider._root_certificate_serial([sm2, rsa, ecc]) == expected +def test_certificate_public_key_uses_sdk_compatible_subject_public_key_info(): + from cryptography.hazmat.primitives.asymmetric import rsa as crypto_rsa + import rsa as sdk_rsa + + private_key = crypto_rsa.generate_private_key(public_exponent=65537, key_size=2048) + + class FakeCertificate: + def public_key(self): + return private_key.public_key() + + public_key = alipay_provider._certificate_public_key(FakeCertificate()) + + assert public_key.startswith("-----BEGIN PUBLIC KEY-----") + parsed = sdk_rsa.PublicKey.load_pkcs1_openssl_pem(public_key) + assert parsed.n == private_key.public_key().public_numbers().n + + def test_certificate_bundle_keeps_valid_certificates_when_one_block_is_unsupported(monkeypatch, tmp_path): bundle = tmp_path / "alipayRootCert.crt" bundle.write_bytes(