【问题标题】:Is it possible to generate on the fly SSL certificates from a root CA in C#?是否可以从 C# 中的根 CA 动态生成 SSL 证书?
【发布时间】:2019-02-13 02:54:25
【问题描述】:

我正在我自己的根 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 流量。

【问题讨论】:

    标签: c# ssl asp.net-core


    【解决方案1】:

    使用CertificateRequest.Create() 方法,我得到一个没有私钥的有效证书。

    真正的证书颁发机构不应将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 语句中包含您的证书对象,以便在不再需要它们时将其处理掉,在这种情况下,您需要第二个变量来保存带有证书的证书)

    【讨论】:

      【解决方案2】:

      鉴于证书请求是使用您的 rsa 实例创建的,您应该能够从中导出私钥。 RSA.ToXmlString() 允许将密钥导出为以后可以使用RSA.FromXmlString() 导入的格式。

      【讨论】:

      • 您好,感谢您的帮助。 RSA.ToXmlString()RSA.FromXmlString() 似乎在 .NET Core 中不起作用并引发 Operation is not supported on this platform 错误。更多信息在this issue submitted to GitHub
      • @RomanPort RSA.ExportParameters() 应该仍然适用于 .NET Core
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-29
      • 2019-12-19
      • 2013-08-30
      相关资源
      最近更新 更多