如何使用 C# 创建自签名证书?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13806299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:51:36  来源:igfitidea点击:

How can I create a self-signed certificate using C#?

c#.netcertificateself-signed

提问by Guss

I need to create a self-signed certificate (for local encryption - it's not used to secure communications), using C#.

我需要使用 C# 创建一个自签名证书(用于本地加密 - 它不用于保护通信)。

I've seen some implementations that use P/Invokewith Crypt32.dll, but they are complicated and it's hard to update the parameters - and I would also like to avoid P/Invoke if at all possible.

我已经看到一些使用P/InvokeCrypt32.dll 的实现,但它们很复杂并且很难更新参数 - 如果可能的话,我也想避免 P/Invoke 。

I don't need something that is cross platform - running only on Windows is good enough for me.

我不需要跨平台的东西——只在 Windows 上运行对我来说已经足够了。

Ideally, the result would be an X509Certificate2 object that I can use to insert into the Windows certificate store or export to a PFXfile.

理想情况下,结果将是一个 X509Certificate2 对象,我可以使用它插入到 Windows 证书存储或导出到PFX文件。

采纳答案by Guss

This implementation uses the CX509CertificateRequestCertificateCOM object (and friends - MSDN doc) from certenroll.dllto create a self signed certificate request and sign it.

此实现使用CX509CertificateRequestCertificateCOM 对象(和朋友 - MSDN 文档certenroll.dll来创建自签名证书请求并对其进行签名。

The example below is pretty straight forward (if you ignore the bits of COM stuff that goes on here) and there are a few parts of the code that are really optional (such as EKU) which are none-the-less useful and easy to adapt to your use.

下面的示例非常简单(如果您忽略这里发生的 COM 内容),并且代码中有一些部分是真正可选的(例如 EKU),它们仍然有用且易于使用适应您的使用。

public static X509Certificate2 CreateSelfSignedCertificate(string subjectName)
{
    // create DN for subject and issuer
    var dn = new CX500DistinguishedName();
    dn.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);

    // create a new private key for the certificate
    CX509PrivateKey privateKey = new CX509PrivateKey();
    privateKey.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
    privateKey.MachineContext = true;
    privateKey.Length = 2048;
    privateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; // use is not limited
    privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
    privateKey.Create();

    // Use the stronger SHA512 hashing algorithm
    var hashobj = new CObjectId();
    hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
        ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, 
        AlgorithmFlags.AlgorithmFlagsNone, "SHA512");

    // add extended key usage if you want - look at MSDN for a list of possible OIDs
    var oid = new CObjectId();
    oid.InitializeFromValue("1.3.6.1.5.5.7.3.1"); // SSL server
    var oidlist = new CObjectIds();
    oidlist.Add(oid);
    var eku = new CX509ExtensionEnhancedKeyUsage();
    eku.InitializeEncode(oidlist); 

    // Create the self signing request
    var cert = new CX509CertificateRequestCertificate();
    cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, "");
    cert.Subject = dn;
    cert.Issuer = dn; // the issuer and the subject are the same
    cert.NotBefore = DateTime.Now;
    // this cert expires immediately. Change to whatever makes sense for you
    cert.NotAfter = DateTime.Now; 
    cert.X509Extensions.Add((CX509Extension)eku); // add the EKU
    cert.HashAlgorithm = hashobj; // Specify the hashing algorithm
    cert.Encode(); // encode the certificate

    // Do the final enrollment process
    var enroll = new CX509Enrollment();
    enroll.InitializeFromRequest(cert); // load the certificate
    enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name
    string csr = enroll.CreateRequest(); // Output the request in base64
    // and install it back as the response
    enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
        csr, EncodingType.XCN_CRYPT_STRING_BASE64, ""); // no password
    // output a base64 encoded PKCS#12 so we can import it back to the .Net security classes
    var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
        PFXExportOptions.PFXExportChainWithRoot);

    // instantiate the target class with the PKCS#12 data (and the empty password)
    return new System.Security.Cryptography.X509Certificates.X509Certificate2(
        System.Convert.FromBase64String(base64encoded), "", 
        // mark the private key as exportable (this is usually what you want to do)
        System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable
    );
}

The result can be added to a certificate store using X509Storeor exported using the X509Certificate2methods.

可以X509Store使用这些X509Certificate2方法将结果添加到证书存储或导出。

For a fully managed and not tied to Microsoft's platform, and if you're OK with Mono's licensing, then you can look at X509CertificateBuilderfrom Mono.Security. Mono.Security is standalone from Mono, in that it doesn't need the rest of Mono to run and can be used in any compliant .Net environment (e.g. Microsoft's implementation).

对于一个全面管理,而不是依赖于微软的平台,如果你使用Mono的许可OK,那么你可以看看X509CertificateBuilderMono.Security。Mono.Security 独立于 Mono,因为它不需要 Mono 的其余部分来运行,并且可以在任何兼容的 .Net 环境中使用(例如 Microsoft 的实现)。

回答by dthorpe

You can use the free PluralSight.Crypto libraryto simplify programmatic creation of self-signed X.509 certificates:

您可以使用免费的PluralSight.Crypto 库来简化自签名 X.509 证书的编程创建:

    using (CryptContext ctx = new CryptContext())
    {
        ctx.Open();

        X509Certificate2 cert = ctx.CreateSelfSignedCertificate(
            new SelfSignedCertProperties
            {
                IsPrivateKeyExportable = true,
                KeyBitLength = 4096,
                Name = new X500DistinguishedName("cn=localhost"),
                ValidFrom = DateTime.Today.AddDays(-1),
                ValidTo = DateTime.Today.AddYears(1),
            });

        X509Certificate2UI.DisplayCertificate(cert);
    }

PluralSight.Crypto requires .NET 3.5 or later.

PluralSight.Crypto 需要 .NET 3.5 或更高版本。

回答by dthorpe

Another option is to use the CLR Security extensions libraryfrom CodePlex, which implements a helper function to generate self-signed X.509 certificates:

另一种选择是使用CodePlex的CLR 安全扩展库,它实现了一个辅助函数来生成自签名 X.509 证书:

X509Certificate2 cert = CngKey.CreateSelfSignedCertificate(subjectName);

You can also look at the implementation of that function (in CngKeyExtensionMethods.cs) to see how to create the self-signed certificate explicitly in managed code.

您还可以查看该函数的实现(在 中CngKeyExtensionMethods.cs),以了解如何在托管代码中显式创建自签名证书。

回答by Roger Deep

This is the Powershell version on how to create a certificate. You can use it by executing the command. Check https://technet.microsoft.com/itpro/powershell/windows/pkiclient/new-selfsignedcertificate

这是关于如何创建证书的 Powershell 版本。您可以通过执行命令来使用它。检查https://technet.microsoft.com/itpro/powershell/windows/pkiclient/new-selfsignedcertificate

Edit: forgot to say that after you create the certificate, you can use the Windows "manage computer certificates" program, to export the certificate to .CER or other type.

编辑:忘了说创建证书后,您可以使用Windows“管理计算机证书”程序,将证书导出为.CER或其他类型。

回答by Duncan Smart

Since .NET 4.7.2 you can create self-signed certs using System.Security.Cryptography.X509Certificates.CertificateRequest.

从 .NET 4.7.2 开始,您可以使用System.Security.Cryptography.X509Certificates.CertificateRequest创建自签名证书。

For example:

例如:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

public class CertificateUtil
{
    static void MakeCert()
    {
        var ecdsa = ECDsa.Create(); // generate asymmetric key pair
        var req = new CertificateRequest("cn=foobar", ecdsa, HashAlgorithmName.SHA256);
        var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(5));

        // Create PFX (PKCS #12) with private key
        File.WriteAllBytes("c:\temp\mycert.pfx", cert.Export(X509ContentType.Pfx, "P@55w0rd"));

        // Create Base 64 encoded CER (public key only)
        File.WriteAllText("c:\temp\mycert.cer",
            "-----BEGIN CERTIFICATE-----\r\n"
            + Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks)
            + "\r\n-----END CERTIFICATE-----");
    }
}