如何在.NET中创建全新的x509Certificate2?

33

我从网络上谷歌搜索到很多生成一个新的x509Certificate2文件的例子,但是没有例子展示如何在.Net中从头开始生成一个全新的x509Certificate2

有没有人可以告诉我如何在.Net中实现呢?


1
似乎没有人知道这件事。在 .NET 中,x509Certificate2 好像只能用于读取 x509Certificate2 证书,而不是生成它们,对吗? - travellover
1
是的,通过X509Certificate2拥有的方法和构造函数,我们只能导入并获取其属性。 - pinichi
6个回答

21

结账 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
这应该是正确的答案。纯.NET,没有第三方库。感谢你的工作! - canvee

20

以下是可以使用的代码:

    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库的引用。


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

9

OpenSSL用于创建x509证书

1.从以下链接下载Win64 OpenSSL。(Win64 OpenSSL v1.1.0j - 37MB安装程序) URL-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.现在我们在桌面上有两个名为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。


2
您可以使用PINVOKE调用Crypt32来创建自签名证书。有一些可用的示例代码可生成证书并将其放入证书存储中。
另外,还有Keith Brown的证书生成器,它是用托管代码编写的,并且有一个您可以使用的库。
或者,您可以使用BouncyCastle使用Org.BouncyCastle.X509.X509V3CertificateGenerator和Org.BouncyCastle.Security.DotNetUtilities中的实用程序方法,并调用ToX509Certificate()。
如果你想创建一个请求并让一个 CA 签名,那么在 .NET 中这实际上更容易,因为大多数这些类可以作为 COM 交互 DLL 导入。但这是另一个问题了。

实际上,Keith Brown的代码也只是使用P/Invoke调用Crypt32方法。 - Rasmus Faber
好的,它很好地封装了它,这样你就不必自己去做了。因为Crypt-32不太友好 :) - blowdart
Keith Brown的链接已经失效了,有人有最新的链接吗? - Roger Lipscombe
http://blog.pluralsight.com/2012/02/13/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net/ - Mladen Mihajlovic

-1

我认为你不能使用那个API来完成它。但是你可以使用Bouncy Castle (http://www.bouncycastle.org)创建一个对象,然后将该对象转换为X509Certificate2对象(BC有一些实用类来完成这个过程)。

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

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


-4
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。虽然您的代码看起来很正常,但如果您在答案中添加一些解释重要部分的文本或链接到官方文档,那将是非常好的。 - m02ph3u5
InitConfiguration()是什么? - clamchoda
1
这将枚举系统存储中的证书。它不会创建新的证书。 - Rainmaker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接