如何在.net 中创建一个全新的 x509Certificate2?

Posted

技术标签:

【中文标题】如何在.net 中创建一个全新的 x509Certificate2?【英文标题】:how to create a completely new x509Certificate2 in .net? 【发布时间】:2011-01-19 21:23:39 【问题描述】:

我从网络上搜索它,找到许多示例以从 .net 中的文件生成新的 x509Certificate2,但没有一个示例显示如何在 .net 中从头开始生成全新的 x509Certificate2。

有没有人可以告诉我如何在.net中做到这一点?

非常感谢。

【问题讨论】:

似乎没有人知道这一点。似乎 .net 中的 x509Certificate2 仅用于读取 x509Certificate2 证书而不是生成证书,对吧? 是的,使用X509Certificate2的方法和构造函数,我们只能导入,获取它的属性。 【参考方案1】:

这是您可以使用的代码:

    static X509Certificate2 GenerateCertificate(string certName)
    
        var keypairgen = new RsaKeyPairGenerator();
        keypairgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));

        var keypair = keypairgen.GenerateKeyPair();

        var gen = new X509V3CertificateGenerator();

        var CN = new X509Name("CN=" + certName);
        var SN = BigInteger.ProbablePrime(120, new Random());

        gen.SetSerialNumber(SN);
        gen.SetSubjectDN(CN);
        gen.SetIssuerDN(CN);
        gen.SetNotAfter(DateTime.MaxValue);
        gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
        gen.SetSignatureAlgorithm("MD5WithRSA");
        gen.SetPublicKey(keypair.Public);           

        var newCert = gen.Generate(keypair.Private);

        return new X509Certificate2(DotNetUtilities.ToX509Certificate((Org.BouncyCastle.X509.X509Certificate)newCert));
    

为此,不要忘记添加对BouncyCastle library的引用

【讨论】:

我可能错了,但新的 Random() 不应该是静态只读 Random 实例吗?如果你每次都创建一个新实例,它每次都会在 ProbablePrime 中返回相同的随机数。 我通过 VeraCode 运行了 BouncyCastle (1.7.1),我发现它的 BigInteger 实现没有提供足够的熵。这对库使用的素数生成的有效性提出了质疑。 @Mr.Young 如果您愿意,可以通过私信了解与您的上述评论相关的更多详细信息。 BigInteger 不是密钥生成器使用的任何熵的来源;我们有一个 SecureRandom 类。在我们最新的代码中,这实质上是转发到系统 RNG,但可能是早期版本不太理想。在 BigInteger 中,Random 类仅用于选择 Miller-Rabin 随机基来测试可能的素数。【参考方案2】:

打开 ssl 以创建 x509 证书

1.从以下链接下载 Win64 Openssl。(Win64 OpenSSL v1.1.0j - 37mb 安装程序) 网址 - https://slproweb.com/products/Win32OpenSSL.html

2.安装后设置系统路径环境变量。(path = C:\OpenSSL-Win64\bin)

3.打开命令提示符并将目录更改为桌面。

4.创建密钥的命令: 私钥:openssl req -x509 -days 365 -newkey rsa:2048 -keyout cert-key.pem -out cert.pem 输入命令并按照说明进行操作。

5.现在我们在桌面上有 2 个文件,分别名为 cert-key.pem 和 cert.pem。要创建 .pfx 文件,请运行以下命令 openssl pkcs12 -export -in cert.pem -inkey cert-key.pem -out x509-cert.pfx 并按照说明进行操作(输入相同的密码)。

6.创建公钥的命令: openssl pkcs12 -in x509-cert.pfx -clcerts -nokeys -out x509-cert-public.pem 并按照说明进行操作。

7.向mmc注册证书。

【讨论】:

【参考方案3】:

结帐CertificateRequest(命名空间:System.Security.Cryptography.X509Certificates)...

 public static X509Certificate2 GenerateSelfSignedCertificate()
    
        string secp256r1Oid = "1.2.840.10045.3.1.7";  //oid for prime256v1(7)  other identifier: secp256r1
        
        string subjectName = "Self-Signed-Cert-Example";

        var ecdsa = ECDsa.Create(ECCurve.CreateFromValue(secp256r1Oid));

        var certRequest = new CertificateRequest($"CN=subjectName", ecdsa, HashAlgorithmName.SHA256);

        //add extensions to the request (just as an example)
        //add keyUsage
        certRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, true));

        X509Certificate2 generatedCert = certRequest.CreateSelfSigned(DateTimeOffset.Now.AddDays(-1), DateTimeOffset.Now.AddYears(10)); // generate the cert and sign!

        X509Certificate2 pfxGeneratedCert = new X509Certificate2(generatedCert.Export(X509ContentType.Pfx)); //has to be turned into pfx or Windows at least throws a security credentials not found during sslStream.connectAsClient or HttpClient request...

     return pfxGeneratedCert;

【讨论】:

【参考方案4】:

您可以使用 PINVOKE 调用 Crypt32 到 create a self signed certificate。有一些sample code 可用,它会为您生成一个并将其放入证书存储中。

还有 Keith Brown 的 certificate generator,它是用托管代码编写的,有 a library you can use。

或者,您可以通过 Org.BouncyCastle.X509.X509V3CertificateGenerator 使用 BouncyCastle 并使用 Org.BouncyCastle.Security.DotNetUtilities 中的实用方法并调用 ToX509Certificate()

如果您想创建一个请求并让它由一个在 .NET 中实际上更容易的 CA 签名,因为这些类中的大多数都可以作为 COM 互操作 DLL 导入。但这是另一个问题。

【讨论】:

实际上 Keith Brown 的代码也只是对 Crypt32 方法使用了 P/Invoke。 嗯,它很好地包裹了它,所以你没有太多。因为 Crypt-32 对 pinvoke 不友好 :) Keith Brown 资料的链接已失效。有人有当前链接吗? blog.pluralsight.com/2012/02/13/…【参考方案5】:

我认为您无法使用该 API 来做到这一点。但是您可以使用 Bouncy Castle (http://www.bouncycastle.org) 创建一个,然后将该对象转换为 X509Certificate2 对象(BC 有一些实用程序类可以做到这一点)。

-编辑- 看看这些 BC 类:X509V3CertificateGenerator 和 X509Certificate

稍后将 BC X509Certificate 对象转换为常规 X509Certificate2 对象的 BC 实用程序类是:DotNetUtilities

【讨论】:

【参考方案6】:
public X509Certificate2 GetCertificate()

    var config = InitConfiguration();
    var certificateSubject = "X509Subject";
    var certificateStoreName = "X509StoreName";
    var certificateStoreLocation = "X509StoreLocation";
    var thumbPrint = "ThumbPrint";

    var storeName = (StoreName)Enum.Parse(typeof(StoreName), certificateStoreName, true);
    var storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), certificateStoreLocation, true);

    var certificateStore = new X509Store(storeName, storeLocation);
    certificateStore.Open(OpenFlags.ReadOnly);

    foreach (var storeCertificate in certificateStore.Certificates)
    
        if (storeCertificate.Thumbprint.ToLower(System.Globalization.CultureInfo.CurrentCulture) == thumbPrint.ToLower(System.Globalization.CultureInfo.CurrentCulture))
        return storeCertificate;
        
    
certificateStore.Close();
    return null;

【讨论】:

欢迎来到 SO。虽然您的代码看起来合法,但如果您在答案中添加一些文本来解释重要部分或链接到官方文档,那就太好了。 什么是InitConfiguration() 这会枚举系统存储中的证书。它不会创建新证书

以上是关于如何在.net 中创建一个全新的 x509Certificate2?的主要内容,如果未能解决你的问题,请参考以下文章

C#如何验证Root-CA-Cert证书(x509)链?

如何在Java中检索/计算X509证书的指纹?

如何在此文件夹中创建一个全新的 Angular 组件?为啥我使用 Angular CLI 获得此错误消息?

引起:javax.net.ssl.SSLHandshakeException:java.security.cert.CertificateException:java(spring)中没有可用的X50

X509Certificate 构造函数异常

如何从 Java 中的 X509Certificate 中提取 CN?