Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a self-signed certificate on the fly

I searched around, but I didn't find a clear example. I want to create a self-signed (self-)trusted certificate programmatically (C#), following these steps:

STEP 1:

Create a root CA certificate on the fly and add it to the certificate store in the folder "Trusted Root certification Authorities"

I want to do exactly what this command line tool does:

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

STEP 2:

Create a certificate based on the previously created root CA certificate and put it in the certificate store, in the folder "Personal"

I want to do exactly what this command line tool does:

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 

I want to obtain this:

Enter image description here

I did that (see the following code - STEP 1). How do I make STEP 2? Target machines is Windows XP/7.

I tried both a pure .NET approach and Bouncy Castle library.

// 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; } 
like image 239
wakeupneo Avatar asked Mar 06 '14 16:03

wakeupneo


People also ask

How do you get a self signed SSL certificate?

Open IIS manager (inetmgr) on your web server. Click on the server node (one of the root nodes) in the left panel, and double click "Server certificates". Click on "Create Self-Signed Certificate" on the right panel and type in anything you want for the friendly name.


2 Answers

Ok, thanks for the help. Here it is the working code:

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; } 
like image 35
wakeupneo Avatar answered Sep 22 '22 23:09

wakeupneo


I edited the answer to do the root certificate first and then issue an end entity certificate.

Here is some example of generating a self-signed certificate through 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; } 

And add to the store (your code slightly modified):

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; } 

And usage:

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

I have not compiled this example code after @wakeupneo comments. @wakeupneo, you might have to slightly edit the code and add proper extensions to each certificate.

like image 67
pepo Avatar answered Sep 22 '22 23:09

pepo