【问题标题】:Generate a self-signed certificate on the fly即时生成自签名证书
【发布时间】:2014-04-09 11:00:07
【问题描述】:

我四处寻找,但没有找到一个明确的例子。 我想以编程方式 (C#) 创建一个自签名(自)受信任的证书,请执行以下步骤:

第 1 步:

即时创建根 CA 证书并将其添加到“受信任的根证书颁发机构”文件夹中的证书存储中

我想做这个命令行工具所做的事情:

makecert.exe -sk RootCA -sky signature -pe -n CN=MY_CA -r -sr LocalMachine -ss Root MyCA.cer

第 2 步:

根据之前创建的根 CA 证书创建一个证书,并将其放入证书存储中的“个人”文件夹中

我想做这个命令行工具所做的事情:

makecert.exe -sk server -sky exchange -pe -n CN=127.0.0.1 -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyCertificate.cer

我想得到这个:

我做到了(请参阅以下代码 - 第 1 步)。如何进行第 2 步?目标机器是 Windows XP/7。

我尝试了纯 .NET 方法和 Bouncy Castle

// STEP 1
mycerRoot = generateRootCertV1("MY_CA"); // Tried also generateRootCertV2(BouncyCastle)
addCertToStore(mycerRoot, StoreName.Root, StoreLocation.LocalMachine);

// STEP 2
mycer = generateCert("127.0.0.1", mycerRoot); // ?????? <-- Something like that How to implement generateCert??
addCertToStore(mycer, StoreName.My, StoreLocation.LocalMachine);

public static Org.BouncyCastle.X509.X509Certificate generateRootCertV2(string certName)
{
    X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();

    X509Name CN = new X509Name("CN=" + certName);

    RsaKeyPairGenerator keypairgen = new RsaKeyPairGenerator();
    keypairgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));

    AsymmetricCipherKeyPair keypair = keypairgen.GenerateKeyPair();

    certGen.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));
    certGen.SetIssuerDN(CN);
    certGen.SetNotAfter(DateTime.MaxValue);
    certGen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
    certGen.SetSubjectDN(CN);
    certGen.SetPublicKey(keypair.Public);
    certGen.SetSignatureAlgorithm("MD5WithRSA");

    Org.BouncyCastle.X509.X509Certificate newCert = certGen.Generate(keypair.Private);

    return newCert;
}

public static X509Certificate2 GenerateRootCertV1(string HostNameOrIP_or_CertName)
{
    X509Certificate2 cert = null;

    try
    {
        using (CryptContext ctx = new CryptContext())
        {
            ctx.Open();
            cert = ctx.CreateSelfSignedCertificate(
                new SelfSignedCertProperties
                {
                    IsPrivateKeyExportable = true,
                    KeyBitLength = 4096,
                    Name = new X500DistinguishedName("cn=" + HostNameOrIP_or_CertName),
                    ValidFrom = DateTime.Today.AddDays(-1),
                    ValidTo = DateTime.Today.AddYears(20),
                });
        }
    }
    catch (Exception ex)
    {
    }

    return cert;
}

public static bool addCertToStore(X509Certificate2 cert, StoreName st, StoreLocation sl)
{
    bool bRet = false;

    try
    {
        X509Store store = new X509Store(st, sl);
        store.Open(OpenFlags.ReadWrite);

        if (cert != null)
        {
            byte[] pfx = cert.Export(X509ContentType.Pfx);
            cert = new X509Certificate2(pfx, (string)null, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

            if (!certExists(store, cert.SubjectName.Name))
            {
                store.Add(cert);
                bRet = true;
            }
        }
        store.Close();
    }
    catch
    {

    }
    return bRet;
}

【问题讨论】:

标签: c# .net ssl-certificate x509certificate bouncycastle


【解决方案1】:

我编辑了答案,先做根证书,然后颁发最终实体证书。

以下是通过 Bouncy Castle 生成自签名证书的一些示例:

public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey,  int keyStrength = 2048)
{
    // Generating Random Numbers
    var randomGenerator = new CryptoApiRandomGenerator();
    var random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    var certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
    certificateGenerator.SetSerialNumber(serialNumber);

    // Signature Algorithm
    const string signatureAlgorithm = "SHA256WithRSA";
    certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);

    // Issuer and Subject Name
    var subjectDN = new X509Name(subjectName);
    var issuerDN = new X509Name(issuerName);
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    // Valid For
    var notBefore = DateTime.UtcNow.Date;
    var notAfter = notBefore.AddYears(2);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    // Subject Public Key
    AsymmetricCipherKeyPair subjectKeyPair;
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    var keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    // Generating the Certificate
    var issuerKeyPair = subjectKeyPair;

    // Selfsign certificate
    var certificate = certificateGenerator.Generate(issuerPrivKey, random);

    // Corresponding private key
    PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);


    // Merge into X509Certificate2
    var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

    var seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
    if (seq.Count != 9)
        throw new PemException("malformed sequence in RSA private key");

    var rsa = new RsaPrivateKeyStructure(seq);
    RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
        rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);

    x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
    return x509;
}


public static AsymmetricKeyParameter GenerateCACertificate(string subjectName, int keyStrength = 2048)
{
    // Generating Random Numbers
    var randomGenerator = new CryptoApiRandomGenerator();
    var random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    var certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
    certificateGenerator.SetSerialNumber(serialNumber);

    // Signature Algorithm
    const string signatureAlgorithm = "SHA256WithRSA";
    certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);

    // Issuer and Subject Name
    var subjectDN = new X509Name(subjectName);
    var issuerDN = subjectDN;
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    // Valid For
    var notBefore = DateTime.UtcNow.Date;
    var notAfter = notBefore.AddYears(2);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    // Subject Public Key
    AsymmetricCipherKeyPair subjectKeyPair;
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    var keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    // Generating the Certificate
    var issuerKeyPair = subjectKeyPair;

    // Selfsign certificate
    var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
    var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

    // Add CA certificate to Root store
    addCertToStore(cert, StoreName.Root, StoreLocation.CurrentUser);

    return issuerKeyPair.Private;
}

并添加到商店(您的代码稍作修改):

public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
{
    bool bRet = false;

    try
    {
        X509Store store = new X509Store(st, sl);
        store.Open(OpenFlags.ReadWrite);
        store.Add(cert);

        store.Close();
    }
    catch
    {

    }

    return bRet;
}

及用法:

var caPrivKey = GenerateCACertificate("CN=root ca");
var cert = GenerateSelfSignedCertificate("CN=127.0.01", "CN=root ca", caPrivKey);
addCertToStore(cert, StoreName.My, StoreLocation.CurrentUser);

@wakeupneo cmets 之后我还没有编译这个示例代码。 @wakeupneo,您可能需要稍微编辑代码并为每个证书添加适当的扩展。

【讨论】:

    【解决方案2】:

    好的,感谢您的帮助。这是工作代码:

    private void button_Click(object sender, EventArgs e)
    {
        AsymmetricKeyParameter myCAprivateKey = null;
    
        // Generate a root CA cert and obtain the privateKey
        X509Certificate2 MyRootCAcert = GenerateCACertificate("CN=MYTESTCA", ref myCAprivateKey);
    
        // Add CA certificate to store
        addCertToStore(MyRootCAcert, StoreName.Root, StoreLocation.LocalMachine);
    
        // Generate certificate based on the CA certificate privateKey
        X509Certificate2 MyCert = GenerateSelfSignedCertificate("CN=127.0.01", "CN=MYTESTCA", myCAprivateKey);
    
        // Add certificate to store
        addCertToStore(MyCert, StoreName.My, StoreLocation.LocalMachine);
    
        MessageBox.Show("Done!");
    }
    
    
    public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey)
    {
        const int keyStrength = 2048;
    
        // Generating Random Numbers
        CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
        SecureRandom random = new SecureRandom(randomGenerator);
    
        // The Certificate Generator
        X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
    
        // Serial Number
        BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
        certificateGenerator.SetSerialNumber(serialNumber);
    
        // Signature Algorithm
        const string signatureAlgorithm = "SHA256WithRSA";
        certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
    
        // Issuer and Subject Name
        X509Name subjectDN = new X509Name(subjectName);
        X509Name issuerDN = new X509Name(issuerName);
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);
    
        // Valid For
        DateTime notBefore = DateTime.UtcNow.Date;
        DateTime notAfter = notBefore.AddYears(2);
    
        certificateGenerator.SetNotBefore(notBefore);
        certificateGenerator.SetNotAfter(notAfter);
    
        // Subject Public Key
        AsymmetricCipherKeyPair subjectKeyPair;
        var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
        var keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(keyGenerationParameters);
        subjectKeyPair = keyPairGenerator.GenerateKeyPair();
    
        certificateGenerator.SetPublicKey(subjectKeyPair.Public);
    
        // Generating the Certificate
        AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
    
        // Selfsign certificate
        Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerPrivKey, random);
    
        // Corresponding private key
        PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
    
        // Merge into X509Certificate2
        X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
    
        Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
        if (seq.Count != 9)
        {
            //throw new PemException("malformed sequence in RSA private key");
        }
    
        RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
        RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
            rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
    
        x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
        return x509;
    
    }
    
    public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey)
    {
        const int keyStrength = 2048;
    
        // Generating Random Numbers
        CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
        SecureRandom random = new SecureRandom(randomGenerator);
    
        // The Certificate Generator
        X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
    
        // Serial Number
        BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
        certificateGenerator.SetSerialNumber(serialNumber);
    
        // Signature Algorithm
        const string signatureAlgorithm = "SHA256WithRSA";
        certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
    
        // Issuer and Subject Name
        X509Name subjectDN = new X509Name(subjectName);
        X509Name issuerDN = subjectDN;
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);
    
        // Valid For
        DateTime notBefore = DateTime.UtcNow.Date;
        DateTime notAfter = notBefore.AddYears(2);
    
        certificateGenerator.SetNotBefore(notBefore);
        certificateGenerator.SetNotAfter(notAfter);
    
        // Subject Public Key
        AsymmetricCipherKeyPair subjectKeyPair;
        KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
        RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(keyGenerationParameters);
        subjectKeyPair = keyPairGenerator.GenerateKeyPair();
    
        certificateGenerator.SetPublicKey(subjectKeyPair.Public);
    
        // Generating the Certificate
        AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
    
        // Selfsign certificate
        Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
        X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
    
        CaPrivateKey = issuerKeyPair.Private;
    
        return x509;
        //return issuerKeyPair.Private;
    }
    
    public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
    {
        bool bRet = false;
    
        try
        {
            X509Store store = new X509Store(st, sl);
            store.Open(OpenFlags.ReadWrite);
            store.Add(cert);
    
            store.Close();
        }
        catch
        {
    
        }
        return bRet;
    }
    

    【讨论】:

      【解决方案3】:

      在整合了多个帖子的更改后,我终于得到了这段代码!

      static void Main(string[] args)
      {
          AsymmetricKeyParameter caPrivateKey = null;
          var caCert = GenerateCACertificate("CN=MyROOTCA", ref caPrivateKey);
          addCertToStore(caCert, StoreName.Root, StoreLocation.LocalMachine);
      
          var clientCert = GenerateSelfSignedCertificate("CN=127.0.0.1", "CN=MyROOTCA", caPrivateKey);
      
          var p12 = clientCert.Export(X509ContentType.Pfx);
      
          addCertToStore(new X509Certificate2(p12, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet), StoreName.My, StoreLocation.LocalMachine);
      }
      
      public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey)
      {
          const int keyStrength = 2048;
      
          // Generating Random Numbers
          CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
          SecureRandom random = new SecureRandom(randomGenerator);
      
          // The Certificate Generator
          X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
      
          // Serial Number
          BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
          certificateGenerator.SetSerialNumber(serialNumber);
      
          // Signature Algorithm
          const string signatureAlgorithm = "SHA256WithRSA";
          certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
      
          // Issuer and Subject Name
          X509Name subjectDN = new X509Name(subjectName);
          X509Name issuerDN = new X509Name(issuerName);
          certificateGenerator.SetIssuerDN(issuerDN);
          certificateGenerator.SetSubjectDN(subjectDN);
      
          // Valid For
          DateTime notBefore = DateTime.UtcNow.Date;
          DateTime notAfter = notBefore.AddYears(2);
      
          certificateGenerator.SetNotBefore(notBefore);
          certificateGenerator.SetNotAfter(notAfter);
      
          // Subject Public Key
          AsymmetricCipherKeyPair subjectKeyPair;
          var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
          var keyPairGenerator = new RsaKeyPairGenerator();
          keyPairGenerator.Init(keyGenerationParameters);
          subjectKeyPair = keyPairGenerator.GenerateKeyPair();
      
          certificateGenerator.SetPublicKey(subjectKeyPair.Public);
      
          // Generating the Certificate
          AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
      
          // Selfsign certificate
          Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerPrivKey, random);
      
      
          // Corresponding private key
          PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
      
      
          // Merge into X509Certificate2
          X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
      
          Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
          if (seq.Count != 9)
          {
              //throw new PemException("malformed sequence in RSA private key");
          }
      
          RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
          RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
              rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
      
          x509.PrivateKey = ToDotNetKey(rsaparams); //x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
          return x509;
      }
      
      public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
      {
          var cspParams = new CspParameters
          {
              KeyContainerName = Guid.NewGuid().ToString(),
              KeyNumber = (int)KeyNumber.Exchange,
              Flags = CspProviderFlags.UseMachineKeyStore
          };
      
          var rsaProvider = new RSACryptoServiceProvider(cspParams);
          var parameters = new RSAParameters
          {
              Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
              P = privateKey.P.ToByteArrayUnsigned(),
              Q = privateKey.Q.ToByteArrayUnsigned(),
              DP = privateKey.DP.ToByteArrayUnsigned(),
              DQ = privateKey.DQ.ToByteArrayUnsigned(),
              InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
              D = privateKey.Exponent.ToByteArrayUnsigned(),
              Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
          };
      
          rsaProvider.ImportParameters(parameters);
          return rsaProvider;
      }
      
      public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey)
      {
          const int keyStrength = 2048;
      
          // Generating Random Numbers
          CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
          SecureRandom random = new SecureRandom(randomGenerator);
      
          // The Certificate Generator
          X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
      
          // Serial Number
          BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
          certificateGenerator.SetSerialNumber(serialNumber);
      
          // Signature Algorithm
          const string signatureAlgorithm = "SHA256WithRSA";
          certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
      
          // Issuer and Subject Name
          X509Name subjectDN = new X509Name(subjectName);
          X509Name issuerDN = subjectDN;
          certificateGenerator.SetIssuerDN(issuerDN);
          certificateGenerator.SetSubjectDN(subjectDN);
      
          // Valid For
          DateTime notBefore = DateTime.UtcNow.Date;
          DateTime notAfter = notBefore.AddYears(2);
      
          certificateGenerator.SetNotBefore(notBefore);
          certificateGenerator.SetNotAfter(notAfter);
      
          // Subject Public Key
          AsymmetricCipherKeyPair subjectKeyPair;
          KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
          RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
          keyPairGenerator.Init(keyGenerationParameters);
          subjectKeyPair = keyPairGenerator.GenerateKeyPair();
      
          certificateGenerator.SetPublicKey(subjectKeyPair.Public);
      
          // Generating the Certificate
          AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
      
          // Selfsign certificate
          Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
          X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
      
          CaPrivateKey = issuerKeyPair.Private;
      
          return x509;
          //return issuerKeyPair.Private;
      }
      
      public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
      {
          bool bRet = false;
      
          try
          {
              X509Store store = new X509Store(st, sl);
              store.Open(OpenFlags.ReadWrite);
              store.Add(cert);
      
              store.Close();
          }
          catch
          {
      
          }
      
          return bRet;
      }
      

      【讨论】:

      • 谢谢。我以此为起点创建了 2 个证书。第一个是“受信任的权威”,第二个是由(第一个)签署的。我的对它有一个“微软服务总线”的扭曲。但我能够添加“主题备用名称”和一些 KeyUsages。我在这里发布了我的版本:granadacoder.wordpress.com/2016/11/04/…
      【解决方案4】:

      我们在测试中使用以下代码

      (a) NuGet 依赖:Bouncy Castle 1.7.0

      <package id="BouncyCastle" version="1.7.0" targetFramework="net40" />
      

      (b) 自签名、中间和 CA 证书的生成器:

      namespace Transport.Tests
      {
          using System;
          using System.Security.Cryptography;
          using System.Security.Cryptography.X509Certificates;
          using Org.BouncyCastle.Asn1;
          using Org.BouncyCastle.Asn1.Pkcs;
          using Org.BouncyCastle.Asn1.X509;
          using Org.BouncyCastle.Crypto;
          using Org.BouncyCastle.Crypto.Generators;
          using Org.BouncyCastle.Crypto.Parameters;
          using Org.BouncyCastle.Crypto.Prng;
          using Org.BouncyCastle.Math;
          using Org.BouncyCastle.OpenSsl;
          using Org.BouncyCastle.Pkcs;
          using Org.BouncyCastle.Security;
          using Org.BouncyCastle.Utilities;
          using Org.BouncyCastle.X509;
          using Org.BouncyCastle.X509.Extension;
      
          public class X509Certificate2Builder
          {
              public string SubjectName
              { set { _subjectName = value; } }
      
              public string IssuerName
              { set { _issuerName = value; } }
      
              public AsymmetricAlgorithm IssuerPrivateKey
              { set { _issuerPrivateKey = value; } }
      
              public X509Certificate2 Issuer
              {
                  set
                  {
                      _issuer = value;
                      _issuerName = value.IssuerName.Name;
                      if (value.HasPrivateKey)
                          _issuerPrivateKey = value.PrivateKey;
                  }
              }
      
              public int? KeyStrength
              { set { _keyStrength = value ?? 2048; } }
      
              public DateTime? NotBefore
              { set { _notBefore = value; } }
      
              public DateTime? NotAfter
              { set { _notAfter = value; } }
      
              public bool Intermediate
              { set { _intermediate = value; } }
      
              private string _subjectName;
              private X509Certificate2 _issuer;
              private string _issuerName;
              private AsymmetricAlgorithm _issuerPrivateKey;
              private int _keyStrength = 2048;
              private DateTime? _notBefore;
              private DateTime? _notAfter;
              private bool _intermediate = true;
      
              public X509Certificate2 Build()
              {
                  // Generating Random Numbers
                  var randomGenerator = new CryptoApiRandomGenerator();
                  var random = new SecureRandom(randomGenerator);
      
                  // The Certificate Generator
                  var certificateGenerator = new X509V3CertificateGenerator();
      
                  // Serial Number
                  var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
                  certificateGenerator.SetSerialNumber(serialNumber);
      
                  // Signature Algorithm
                  certificateGenerator.SetSignatureAlgorithm("SHA256WithRSA");
      
                  // Issuer and Subject Name
                  certificateGenerator.SetIssuerDN(new X509Name(_issuerName ?? _subjectName));
                  certificateGenerator.SetSubjectDN(new X509Name(_subjectName));
      
                  // Authority Key Identifier
                  if (_issuer != null)
                  {
                      var authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(
                          DotNetUtilities.FromX509Certificate(_issuer));
                      certificateGenerator.AddExtension(
                          X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier);
                  }
      
                  // Basic Constraints - certificate is allowed to be used as intermediate.
                  certificateGenerator.AddExtension(
                      X509Extensions.BasicConstraints.Id, true, new BasicConstraints(_intermediate));
      
                  // Valid For
                  certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date);
                  certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(2));
      
                  // Subject Public Key
                  var keyGenerationParameters = new KeyGenerationParameters(random, _keyStrength);
                  var keyPairGenerator = new RsaKeyPairGenerator();
                  keyPairGenerator.Init(keyGenerationParameters);
      
                  var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
                  var issuerKeyPair = _issuerPrivateKey == null
                      ? subjectKeyPair
                      : DotNetUtilities.GetKeyPair(_issuerPrivateKey);
      
                  certificateGenerator.SetPublicKey(subjectKeyPair.Public);
      
                  // selfsign certificate
                  var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
      
                  // Merge into X509Certificate2
                  return new X509Certificate2(certificate.GetEncoded())
                  {
                      PrivateKey = ConvertToRsaPrivateKey(subjectKeyPair)
                  };
              }
      
              private static AsymmetricAlgorithm ConvertToRsaPrivateKey(AsymmetricCipherKeyPair keyPair)
              {
                  var keyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
                  var seq = (Asn1Sequence) Asn1Object.FromByteArray(keyInfo.PrivateKey.GetDerEncoded());
                  if (seq.Count != 9)
                      throw new PemException("malformed sequence in RSA private key");
      
                  var rsa = new RsaPrivateKeyStructure(seq);
                  var rsaparams = new RsaPrivateCrtKeyParameters(
                      rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1,
                      rsa.Exponent2, rsa.Coefficient);
      
                  return DotNetUtilities.ToRSA(rsaparams);
              }
          }
      }
      

      (c) 示例用法:

      var ca1 = new X509Certificate2Builder {SubjectName = "CN=Test CA1"}.Build();
      var in1A = new X509Certificate2Builder { SubjectName = "CN=Intermediate 1A", Issuer = ca1}.Build();
      var in1B = new X509Certificate2Builder { SubjectName = "CN=Intermediate 1B", Issuer = in1A}.Build();
      var cert1 = new X509Certificate2Builder { SubjectName = "CN=Test 1", Issuer = in1B, Intermediate = false }.Build();
      var cert1B = new X509Certificate2Builder { SubjectName = "CN=Test 1B", Issuer = cert1}.Build();
      
      var ca2 = new X509Certificate2Builder { SubjectName = "CN=Test CA2"}.Build();
      var cert2 = new X509Certificate2Builder { SubjectName = "CN=Test 2", Issuer = ca2, Intermediate = false}.Build();
      
      var invalidCert1 = new X509Certificate2Builder
      {
          SubjectName = "CN=Invalid 1",
          IssuerName = ca1.SubjectName.Name,
          IssuerPrivateKey = ca2.PrivateKey
      }.Build();
      var invalidCert2 = new X509Certificate2Builder
      {
          SubjectName = "CN=Invalid 2",
          Issuer = ca2,
          NotBefore = DateTime.Now.AddDays(1)
      }.Build();
      

      【讨论】:

      【解决方案5】:

      所以在很长一段时间后我完善了我的答案。 我最初的任务是为 WCF 服务动态创建证书。

      我的 Windows 服务应用程序有一个 WCF 服务,如果本地计算机上不存在相关证书,我想在运行时创建通道并创建相关证书。

      以上所有代码都是正确的方法,但是缺少一个。

      您必须使用嵌入的可导出私钥创建证书。

      看到这个link

      这里重点关注sn-p生成私钥的关键部分:

      var cspParams = new CspParameters
      {
            KeyContainerName = Guid.NewGuid().ToString(),
            KeyNumber = (int)KeyNumber.Exchange,
            Flags = CspProviderFlags.UseMachineKeyStore
      };
      

      如果你在执行netsh命令的时候不这样做,你会得到错误1312。例如,netsh命令的:

      netsh http add sslcert ipport=192.168.0.15:8081 certhash=‎5424476237fc2785ed2d0fd620a9131d7c999f6f appid={02639d71-0935-35e8-9d1b-9dd1a2a34627}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多