title: Is it possible to programmatically generate an X509 certificate using only C#?
body: <p>We're trying to generate an X509 certificate (including the private key) programmatically using C# and the <a href="http://www.bouncycastle.org/" rel="noreferrer">BouncyCastle</a> library. We've tried using some of the code from <a href="http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx" rel="noreferrer">this sample by Felix Kollmann</a> but the private key part of the certificate returns null. Code and unit test are as below:</p>
  
  <pre><code>using System;
  using System.Collections;
  using Org.BouncyCastle.Asn1;
  using Org.BouncyCastle.Asn1.X509;
  using Org.BouncyCastle.Crypto;
  using Org.BouncyCastle.Crypto.Generators;
  using Org.BouncyCastle.Crypto.Prng;
  using Org.BouncyCastle.Math;
  using Org.BouncyCastle.Security;
  using Org.BouncyCastle.X509;
  
  namespace MyApp
  {
      public class CertificateGenerator
      {
          /// &lt;summary&gt;
          /// 
          /// &lt;/summary&gt;
          /// &lt;remarks&gt;Based on &lt;see cref="http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx"/&gt;&lt;/remarks&gt;
          /// &lt;param name="subjectName"&gt;&lt;/param&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          public static byte[] GenerateCertificate(string subjectName)
          {
              var kpgen = new RsaKeyPairGenerator();
  
              kpgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));
  
              var kp = kpgen.GenerateKeyPair();
  
              var gen = new X509V3CertificateGenerator();
  
              var certName = new X509Name("CN=" + subjectName);
              var serialNo = BigInteger.ProbablePrime(120, new Random());
  
              gen.SetSerialNumber(serialNo);
              gen.SetSubjectDN(certName);
              gen.SetIssuerDN(certName);
              gen.SetNotAfter(DateTime.Now.AddYears(100));
              gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
              gen.SetSignatureAlgorithm("MD5WithRSA");
              gen.SetPublicKey(kp.Public);
  
              gen.AddExtension(
                  X509Extensions.AuthorityKeyIdentifier.Id,
                  false,
                  new AuthorityKeyIdentifier(
                      SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(kp.Public),
                      new GeneralNames(new GeneralName(certName)),
                      serialNo));
  
              gen.AddExtension(
                  X509Extensions.ExtendedKeyUsage.Id,
                  false,
                  new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") }));
  
              var newCert = gen.Generate(kp.Private);
              return DotNetUtilities.ToX509Certificate(newCert).Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "password");
          }
      }
  }
  </code></pre>
  
  <p>Unit test:</p>
  
  <pre><code>using System.Security.Cryptography;
  using System.Security.Cryptography.X509Certificates;
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  
  namespace MyApp
  {
      [TestClass]
      public class CertificateGeneratorTests
      {
          [TestMethod]
          public void GenerateCertificate_Test_ValidCertificate()
          {
              // Arrange
              string subjectName = "test";
  
              // Act
              byte[] actual = CertificateGenerator.GenerateCertificate(subjectName);
  
              // Assert
              var cert = new X509Certificate2(actual, "password");
              Assert.AreEqual("CN=" + subjectName, cert.Subject);
              Assert.IsInstanceOfType(cert.PrivateKey, typeof(RSACryptoServiceProvider));
          }
      }
  }
  </code></pre>