繁体   English   中英

是否可以从C#中的根CA即时生成SSL证书?

[英]Is it possible to generate on the fly SSL certificates from a root CA in C#?

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

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

使用CertificateRequest.Create()方法,可以获得没有私钥的有效证书。

真实的证书颁发机构不应具有CA的私钥以及与要在同一位置同时创建的证书相匹配的私钥。 除了目前尚无办法解码认证请求(CSR)的事实外,此方法还假定它与提供给CertificateRequest构造函数的仅公用密钥一起使用。

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

  • 客户确定是否需要新证书
  • 客户生成公共/私有密钥对
  • 客户端将公钥和其他必要信息发送到CA(PKCS#10 CertificationRequest或其他方式)
  • CA验证请求
  • CA使用客户端公钥建立CertificateRequest对象
  • CA使用CertificateRequest.Create()生成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语句中using证书对象,以便在不再需要它们时将其丢弃,在这种情况下,您需要第二个变量来保存cert-with-key)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM