JeffreySu/WeiXinMPSDK · error · CryptographicException

证书中未包含 RSA 公钥。

Error message

证书中未包含 RSA 公钥。

What it means

TenPaySignHelper.VerifyTenpaySign verifies WeChat Pay signatures with the platform certificate's RSA public key (RSAPKCS1SignatureDeformatter + SHA256). If the certificate has no RSA public key (GetRSAPublicKey() null), CryptographicException "证书中未包含 RSA 公钥。" is thrown.

Solutions

  1. Pass a base64/DER platform certificate containing an RSA public key.
  2. If the merchant uses SM2, use the SM2 verification path instead of VerifyTenpaySign.
  3. Pre-check new X509Certificate2(bytes).GetRSAPublicKey() != null before verifying.
  4. Refresh platform certificates from WeChat Pay and ensure you use the current one.

Example fix

// before
var ok = TenPaySignHelper.VerifyTenpaySign(sm2Cert, message, signature);
// after
using var x509 = new X509Certificate2(rsaCertBytes);
if (x509.GetRSAPublicKey() == null) throw new InvalidOperationException("需要 RSA 平台证书");
var ok = TenPaySignHelper.VerifyTenpaySign(rsaCertBase64, message, signature);
Defensive patterns

Strategy: validation

Validate before calling

bool CanVerifyWithRsa(string certBase64) {
    using var x509 = new X509Certificate2(Convert.FromBase64String(certBase64));
    return x509.GetRSAPublicKey() != null;
}

Try / catch

try { var ok = TenPaySignHelper.VerifyTenpaySign(cert, message, signature); }
catch (CryptographicException ex) { logger.Error(ex, "平台证书无 RSA 公钥"); }

Prevention

When it happens

Trigger: Verifying a WeChat Pay callback/response signature using a certificate whose key is EC/SM2 instead of RSA, or a malformed certificate that parses without an RSA key.

Common situations: Merchants switched to SM2 certificates/public-key mode but still using the RSA verification path, or passing the wrong cert content (e.g. a public key PEM rather than an X509 cert).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/11c25c0b85319c43. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Helpers/TenPaySignHelper.cs:224

            if (certType == CertType.SM)
            {
                byte[] pubKeyBytes = Convert.FromBase64String(pubKey);
                ECPublicKeyParameters eCPublicKeyParameters = SMPemHelper.LoadPublicKeyToParameters(pubKeyBytes);
                return GmHelper.VerifySm3WithSm2(eCPublicKeyParameters, contentForSign, wechatpaySignatureBase64);
            }
            else
            {
                //Base64 解码 pubKey(必须已经使用 ApiSecurityHelper.GetUnwrapCertKey() 方法进行 Unwrap)
                var bs = Convert.FromBase64String(pubKey);
                //使用 X509Certificate2 证书
                using (var x509 = new X509Certificate2(bs))
                using (var key = x509.GetRSAPublicKey())
                using (var sha256 = SHA256.Create())
                {
                    if (key == null)
                    {
                        throw new CryptographicException("证书中未包含 RSA 公钥。");
                    }

                    //RSAPKCS1SignatureDeformatter 对象
                    RSAPKCS1SignatureDeformatter df = new RSAPKCS1SignatureDeformatter(key);
                    //指定 SHA256
                    df.SetHashAlgorithm("SHA256");
                    //应答签名
                    byte[] signature = Convert.FromBase64String(wechatpaySignatureBase64);
                    //对比签名
                    byte[] compareByte = sha256.ComputeHash(Encoding.UTF8.GetBytes(contentForSign));
                    //验证签名
                    return df.VerifySignature(compareByte, signature);
                }
            }
        }

        /// <summary>
        /// 检验签名,以确保回调是由微信支付发送。

View on GitHub (pinned to be573f6f94)