You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何CertificateRequest的CertificateExtensions无扩展且证书SAN丢失?

问题原因与解决方案

核心原因

生成CSR时添加的SAN扩展属于PKCS#10请求扩展,存储在CSR的Attributes字段中(对应OpenSSL日志里的Requested Extensions),但.NET的CertificateRequest.LoadSigningRequest方法加载CSR后,返回的对象不会将这些请求扩展自动填充到CertificateExtensions集合中。你服务器端代码直接遍历csr.CertificateExtensions,自然找不到任何扩展,导致证书丢失SAN信息。

解决方案

修改服务器端的GenerateCertificateFromCSR方法,从CSR的Attributes中手动解析Pkcs9ExtensionRequest(OID为1.2.840.113549.1.9.14),提取其中的请求扩展并添加到生成的证书中:

public X509Certificate2 GenerateCertificateFromCSR(byte[] csrBytes)
{
    if (csrBytes == null)
    {
        throw new ArgumentNullException(nameof(csrBytes));
    }

    var csr = CertificateRequest.LoadSigningRequest(csrBytes, HashAlgorithmName.SHA256);

    using var caCertificate = new X509Certificate2(_settings.PfxPath, _settings.PfxPassword);
    var subjectName = new X500DistinguishedName(caCertificate.SubjectName);
    var signatureGenerator = X509SignatureGenerator.CreateForRSA(caCertificate.GetRSAPrivateKey(), RSASignaturePadding.Pkcs1);
    var notBefore = DateTimeOffset.UtcNow;
    var notAfter = DateTimeOffset.UtcNow.AddYears(1);
    var serialNumber = GenerateSerialNumber();

    var certificate = csr.Create(subjectName, signatureGenerator, notBefore, notAfter, serialNumber);

    // 提取CSR中的请求扩展
    var extensionRequestOid = new Oid("1.2.840.113549.1.9.14"); // Pkcs9ExtensionRequest标准OID
    var extensionRequestAttr = csr.Attributes.FirstOrDefault(attr => attr.Oid.Value == extensionRequestOid.Value);
    
    if (extensionRequestAttr != null)
    {
        var requestedExtensions = new Pkcs9ExtensionRequest(extensionRequestAttr.RawData).RequestedExtensions;
        foreach (var extension in requestedExtensions)
        {
            var asnData = new AsnEncodedData(extension.Oid, extension.RawData);
            var formattedData = asnData.Format(true);

            _logger.LogDebug("CSR Requested Extension: {ExtensionOid} - {ExtensionFriendlyName} - {ExtensionFormattedData}", 
                extension.Oid?.Value ?? "Unknown", 
                extension.Oid?.FriendlyName ?? "Unknown", 
                formattedData);
            
            // 保留原扩展的Critical标记,添加到证书
            certificate.Extensions.Add(new X509Extension(extension.Oid, extension.RawData, extension.Critical));
        }
    }

    return certificate;
}

补充说明

  • 你生成CSR的代码完全正确,OpenSSL的日志已经验证SAN扩展存在于CSR的请求扩展中。
  • .NET的CertificateRequest对象的CertificateExtensions仅代表证书本身的扩展,而非CSR中请求的扩展,二者存储位置不同,必须手动提取请求扩展。

内容的提问来源于stack exchange,提问作者vitkuz573

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:07:03