简体   繁体   English

C# X509Certificate2 更改颁发者名称

[英]C# X509Certificate2 change issuer name

There is same question 7 years ago but solved using external library. 7 年前有同样的问题,但使用外部库解决了。 Now it is possible to change X509Certificate2 Issuer Name without external library?现在可以在没有外部库的情况下更改 X509Certificate2 Issuer Name吗?

fyi, I'm using .NET Framework 4.7.2仅供参考,我正在使用 .NET 框架 4.7.2

public static X509Certificate2 Create(string host)
{
    var ecdsa = ECDsa.Create();
    var request = new CertificateRequest($"CN={host}", ecdsa, HashAlgorithmName.SHA256);
    var validFrom = DateTimeOffset.UtcNow;
    var validUntil = DateTimeOffset.UtcNow.AddYears(5);
    var certificate = request.CreateSelfSigned(validFrom, validUntil);
    var certificateBytes = certificate.Export(X509ContentType.Pfx);
    // ??? set issuer ???
    return new X509Certificate2(certificateBytes);
}

For a self-signed certificate changing the issuer name would just make for a non-verifiable certificate (unless you share a private key with the issuer, which is a bad idea).对于自签名证书,更改颁发者名称只会生成不可验证的证书(除非您与颁发者共享私钥,这是一个坏主意)。

For a chain-signed certificate you can use one of the CertificateRequest.Create methods to either provide the issuer certificate (its subject name will be the new certificate's issuer name) or you can supply the issuer name and a signature generator (eg X509SignatureGenerator.CreateForECDsa(key) ) for full control (including making the aforementioned non-verifiable certificate).对于链签名证书,您可以使用其中一种CertificateRequest.Create方法来提供颁发者证书(其主题名称将是新证书的颁发者名称),或者您可以提供颁发者名称和签名生成器(例如X509SignatureGenerator.CreateForECDsa(key) ) 用于完全控制(包括制作上述不可验证的证书)。

@bartojs answer is correct I have to use CertificateRequest.Create . @bartojs 答案是正确的,我必须使用CertificateRequest.Create

I'm creating self signing certificate for my MITM Proxy Server application, so here working code for generating certificate in.Net Framework 4.7.2 without external.dll library like Bouncy Castle or CERTENROLLIB我正在为我的 MITM 代理服务器应用程序创建自签名证书,所以这里是在没有 external.dll 库(如 Bouncy Castle 或 CERTENROLLIB)的情况下在.Net Framework 4.7.2 中生成证书的工作代码

public static X509Certificate2 CreateMyCertificate(string host, bool isCA)
{
    var validFrom = DateTimeOffset.UtcNow;
    var validUntil = DateTimeOffset.UtcNow.AddYears(8);
    X509Certificate2 certificate;
    RSA rsaKey = Program.rootRSA;

    if (isCA)
    {
        // create exportable Root private key
        // will be used later as global variable Program.rootRSA
        CspParameters cspParams = new CspParameters
        {
            KeyContainerName = Guid.NewGuid().ToString()
        };

        rsaKey = new RSACryptoServiceProvider(2048, cspParams);
    }

    // Request a certificate with the common name as the host using the key pair.
    // Common Name (AKA CN) represents the server name protected by the SSL certificate.
    var request = new CertificateRequest(
        $"CN={host}",
        rsaKey,
        HashAlgorithmName.SHA256,
        RSASignaturePadding.Pkcs1
    );

    // Add Certificate Extensions
    request.CertificateExtensions.Add(
        new X509EnhancedKeyUsageExtension(
            new OidCollection
            {
                new Oid("1.3.6.1.5.5.7.3.1")
            }, true)
    );

    if (isCA)
    {
        request.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, true, 1, false));
        request.CertificateExtensions.Add(
            new X509SubjectKeyIdentifierExtension(request.PublicKey, false));
        request.CertificateExtensions.Add(
            new X509KeyUsageExtension(X509KeyUsageFlags.CrlSign | X509KeyUsageFlags.KeyCertSign, false));

        certificate = request.CreateSelfSigned(validFrom, validUntil);
    }
    else
    {
        SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddDnsName(host.Replace("*.", ""));
        request.CertificateExtensions.Add(sanBuilder.Build());
        request.CertificateExtensions.Add(new X509Extension("2.5.29.35", Program.authorityKeyIdentifer, false));
        request.CertificateExtensions.Add(new X509KeyUsageExtension(
            X509KeyUsageFlags.KeyEncipherment, false));

        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var unixTime = Convert.ToInt64((DateTime.UtcNow - epoch).TotalSeconds);
        var serial = BitConverter.GetBytes(unixTime);

        certificate = request.Create(Program.rootCert, validFrom, validUntil.AddDays(-5), serial);
        certificate.PrivateKey = Program.rootCert.PrivateKey;
    }

    var certificateBytes = certificate.Export(X509ContentType.Pfx, "");
    // return certificate with persisted private key
    return new X509Certificate2(certificateBytes, "", X509KeyStorageFlags.Exportable);
}

Then use it like:然后像这样使用它:

  1. create global variable and name it like rootCert and rootRSA创建全局变量并将其命名为rootCertrootRSA
  2. on app start check Computer Certificate, if CA not stored generate using在应用程序开始检查计算机证书,如果 CA 未存储生成使用
rootCert = CreateMyCertificate("__MY_ROOT_CERTIFICATE", true);
  1. Export/Store rootCert to trusted Root locationrootCert导出/存储到受信任的根位置
  2. later if there are https connect request we can generate the cert using稍后如果有 https connect请求,我们可以使用生成证书
CreateMyCertificate("stackoverflow.com", false);
  1. when chaining/creating host certificate make sure rootCert is defined, because it will be used in CreateMyCertificate() method, line below链接/创建host证书时,请确保定义了rootCert ,因为它将在CreateMyCertificate()方法中使用,如下行
if (isCA){...}
else
{
    certificate = request.Create(Program.rootCert, validFrom, validUntil.AddDays(-5), serial);
}

note why you shoud not CERTENROLLIB:注意为什么你不应该 CERTENROLLIB:

  • Slow because Its operation need to read directly from computer certificate慢,因为它的操作需要直接从计算机证书中读取
  • RSA generation is also slower than built-in .net 4.7.2 RSA 生成也比内置 .net 4.7.2 慢
  • To get private key we need first to install the cert the we can export to PFX by doing alot installation to the computer certificate it can spamming your computer cert.要获得私钥,我们首先需要安装证书,我们可以通过对计算机证书进行大量安装来导出到 PFX,它可以向您的计算机证书发送垃圾邮件。

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

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