如何以编程方式创建有效的自签名 X509Certificate2,而不是从 .NET Core 中的文件加载

Posted

技术标签:

【中文标题】如何以编程方式创建有效的自签名 X509Certificate2,而不是从 .NET Core 中的文件加载【英文标题】:How to create a valid, self-signed X509Certificate2 programmatically, not loading from file in .NET Core 【发布时间】:2017-08-04 20:20:36 【问题描述】:

我目前所做的是使用 OpenSSL 生成 PFX 文件。这会导致不必要的依赖,尤其是对于 Windows 用户。所以我找到了一些关于如何使用 BouncyCastle 创建自己的证书的示例,但是这个库与 .NET Core 不兼容(或者我找不到兼容的包)。

那么,是否可以仅使用 .NET 核心创建您自己的自签名 X509 证书以避免依赖于 OpenSSL(或任何其他生成证书的外部工具)?

编辑:有人(编辑?)建议这个 SO 问题 How to create a self-signed certificate using C#? 提供了答案。可悲的是,这与 .NET Core 无关。那里接受的答案以This implementation uses the CX509CertificateRequestCertificate COM object (and friends - MSDN doc) from certenroll.dll to create a self signed certificate request and sign it 开头,这显然不是.NET Core ......事实上,没有一个答案与.NET Core 兼容。

【问题讨论】:

How to create a self-signed certificate using C#?的可能重复 技术尚不存在 - “.NET Core. 尚不提供此机制” - docs.microsoft.com/en-us/aspnet/core/security/data-protection/… 【参考方案1】:

我发现this other SO question 让我走上了正轨。证书 API 已添加到 2.0 版本的 .Net Core。我有一个类似下一个的功能来创建自签名证书,我稍后将其导入到 My 存储中以在 IIS 上使用它们。

    private X509Certificate2 buildSelfSignedServerCertificate()
    
        SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddIpAddress(IPAddress.Loopback);
        sanBuilder.AddIpAddress(IPAddress.IPv6Loopback);
        sanBuilder.AddDnsName("localhost");
        sanBuilder.AddDnsName(Environment.MachineName);

        X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN=CertificateName");

        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 certificate= request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
            certificate.FriendlyName = CertificateName;

            return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "WeNeedASaf3rPassword"), "WeNeedASaf3rPassword", X509KeyStorageFlags.MachineKeySet);
        
    

如果您想要 pfx,X509Certificate2 上的导出功能应该可以解决问题。它返回一个包含原始 pfx 数据的字节数组。

【讨论】:

寻找这段代码已经很久了。那里有许多不正确的版本。您可以通过将request.CertificateExtensions.Add 替换为new Request CertificateExtensions = new X509KeyUsageExtension(...), new X509EnhancedKeyUsageExtension(...), sanBuilder.Build() 来简化语法【参考方案2】:

Microsoft 的方式是使用 makecert 和 pvk2pfx(来自 windows SDK)而不是在 .net 代码本身中执行此操作。现在我对.net core还不是很熟悉,但是由于成熟的.net没有原生支持,如果core版本有这个功能,我会很惊讶。

这里是如何做到这一点的描述: https://msdn.microsoft.com/en-us/library/ff699202.aspx

编辑:让我改写一下:没有外部依赖项,它在 .net(核心)中不可用。 在成熟的 .net 中有很多方法,但您需要外部 dll。

【讨论】:

对不起,但同样,这不是很有用。我甚至可以使用 OpenSSL 跨平台生成 PFX 证书。问题是关于如何避免外部依赖——即如何以编程方式创建这样的证书。 查看编辑;我只是给了你一个“微软最佳实践”的链接,以表明这不仅仅是我的预感,而是他们设计它的方式。如果它是本机功能,人们会期望这是他们的答案,而不是一些 SDK 工具。抱歉不够具体。 那篇文章可能有 5-7 年的历史(它引用了最新的 Visual Studio 2010)。那一年,还没有 .NET Core。如何在 Linux 上运行 pvk2pfx?这只是不正确的事情。即使使用 OpenSSL 也比这要好得多。

以上是关于如何以编程方式创建有效的自签名 X509Certificate2,而不是从 .NET Core 中的文件加载的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个最小的虚拟 X509Certificate2?

如何创建一个自签名的SSL证书(X509)

如何以编程方式为 WCF 服务创建自签名证书?

是否可以仅使用 C# 以编程方式生成 X509 证书?

[转]如何创建一个自签名的SSL证书(X509)

iOS适配HTTPS,创建一个自签名的SSL证书(x509)具体步骤