c# - 是否可以在 C# 中从根 CA 动态生成 SSL 证书?

标签 c# ssl asp.net-core

我正在我自己的根 CA 下设置一个服务器,以在 .NET Core 下动态生成 SSL 证书。

我可以使用 CertificateRequest 类生成自签名证书。但是,这些证书显然不受拥有我自己的根 CA 的客户的信任。我正在使用 CertificateRequest.CreateSelfSigned() 方法来执行此操作。但是,我不能使用我的根 CA 来签署这些新证书。使用 CertificateRequest.Create() 方法将生成我的新证书,但它不会提供私钥。

public static X509Certificate2 CreateSelfSignedCertificate(string domain)
{
    SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
    sanBuilder.AddDnsName(domain);

    X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN=On-The-Fly Generated Cert");

    using (RSA rsa = RSA.Create(2048))
    {
        var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

        request.CertificateExtensions.Add(
            new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));


        request.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false));

        request.CertificateExtensions.Add(sanBuilder.Build());

        var ca = new X509Certificate2(File.ReadAllBytes(@"E:\testing_ca_certificate.pfx"), "password"); //Open my root CA cert, generated in OpenSSL

        //Generates a cert, but does not provide a private key.
        var certificate = request.Create(ca, new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(365)), new byte[] { 0, 1, 2, 3 }); 

        //Generates a usable cert, but is not under my root CA
        //var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(365)));

        return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "password"), "password", X509KeyStorageFlags.DefaultKeySet);
    }

}

使用 CertificateRequest.Create() 方法,我获得了一个没有私钥的有效证书。我应该有这个私钥,这样我就可以加密 SSL 流量。

最佳答案

Using the CertificateRequest.Create() method, I get a valid cert without a private key.

真正的证书颁发机构不应该在同一个地方同时拥有CA的私钥和匹配证书的私钥。除了当前无法解码认证请求 (CSR) 的事实之外,此方法假定它与提供给 CertificateRequest 构造函数的公钥一起使用。

按照流程,“预期”模型是:

  • 客户决定是否需要新证书
  • 客户端生成公钥/私钥对
  • 客户端向 CA 发送公钥和其他必要信息(PKCS#10 CertificationRequest,或其他方式)
  • CA 验证请求
  • CA 使用客户端公钥构建CertificateRequest 对象
  • CA 使用 CertificateRequest.Create() 生成证书
  • CA 将证书发回客户端 (cert.RawData)
  • 客户端实例化X509Certificate2实例(只有公钥)
  • 客户端使用 CopyWithPrivateKey(扩展)方法将私钥关联到新的证书对象。
  • 客户现在想做什么就做什么。

所以,之后

//Generates a cert, but does not provide a private key.
var certificate = request.Create(ca, new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(365)), new byte[] { 0, 1, 2, 3 }); 

你应该添加

certificate = certificate.CopyWithPrivateKey(rsa);

(不过,实际上,您应该在 using 语句中包含您的证书对象,以便在不再需要它们时将其丢弃,在这种情况下,您需要第二个变量来保存证书 -键)

关于c# - 是否可以在 C# 中从根 CA 动态生成 SSL 证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54661774/

相关文章:

c# - 使用 Json.net 的 Instagram API

php - 安全地更新证书颁发机构证书

asp.net - 你如何在本地主机上使用 https/SSL?

c# - Serilog 不记录信息日志

asp.net - 如何从ASP.NET Core Web API中删除重定向并返回HTTP 401?

c# - 实数如何以二进制形式表示?

c# - ContentControl 上的双向绑定(bind)

c# - 如何设置 C# Win Forms 应用程序的版本号

ssl - 通过 Apache JMeter 连接到自签名 SSL 网站

asp.net-core - 找不到类型或命名空间 SigninManager<> Identity 3.1.1 Mediatr 8.0.0