Skip to content

Instantly share code, notes, and snippets.

@Maverik
Last active August 4, 2020 10:56
Show Gist options
  • Select an option

  • Save Maverik/5337717aadfb61b09e58 to your computer and use it in GitHub Desktop.

Select an option

Save Maverik/5337717aadfb61b09e58 to your computer and use it in GitHub Desktop.

Revisions

  1. @venomed venomed revised this gist Mar 30, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions CSRGenerator.cs
    Original file line number Diff line number Diff line change
    @@ -114,16 +114,16 @@
    privateKeyPemWriter.WriteObject(pair.Private);
    privateKeyPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    //Push the privateKeyPem Text to a Label on a Page
    privateKeyPem.ToString().Dump("Private Key");

    //Convert BouncyCastle Private Key to .PEM file.
    //Convert BouncyCastle Public Key to .PEM file.
    var publicKeyPem = new StringBuilder();
    var publicKeyPemWriter = new PemWriter(new StringWriter(publicKeyPem));
    publicKeyPemWriter.WriteObject(pair.Public);
    publicKeyPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    //Push the publicKeyPem Text to a Label on a Page
    publicKeyPem.ToString().Dump("Public Key");

    //Generate a self signed x509 certificate from above
  2. @venomed venomed revised this gist Sep 16, 2016. 2 changed files with 164 additions and 87 deletions.
    164 changes: 164 additions & 0 deletions CSRGenerator.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,164 @@
    // this snippet can be easily used in any normal c# project as well by simply removing the .Dump() methods
    // and saving the output into a variable / file of your choice.
    // you'll need to add BouncyCastle.Crypto nuget to use this.
    // tested on 1.8.1
    // OUTPUTS: CSR, Private Key, Public Key, Self-signed Certificate

    using Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.Cms;
    using Org.BouncyCastle.Asn1.Pkcs;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Generators;
    using Org.BouncyCastle.Crypto.Operators;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.OpenSsl;
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.X509.Extension;
    using System.IO;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using X509Extension = Org.BouncyCastle.Asn1.X509.X509Extension;
    using Org.BouncyCastle.Math;
    using Org.BouncyCastle.Crypto.Prng;
    using Org.BouncyCastle.Utilities;

    //The program generates three outputs named CSR, Private Key & Public Key
    //Save each part in seperate files (leave the heading words out).
    //Send the CSR to whomever you're getting the certificate from and save
    //the private key until you get hold of the final certificate
    //the new certificate & this private key will then combine to become
    //final pfx. Please DO NOT lose private key as CSR & Private Key are
    //a pair and one will not work without the other (and may result in monetory
    //loss due to negligence!) Public key can largely be ignored. It's meant for
    //cases where we don't use CA signed public certificates.

    AsymmetricCipherKeyPair pair;
    Pkcs10CertificationRequest csr;
    Asn1SignatureFactory signatureFactory;
    var random = new SecureRandom(new CryptoApiRandomGenerator());

    var ecMode = false;
    var values = new Dictionary<DerObjectIdentifier, string> {
    {X509Name.CN, "Xero Compensator"}, //domain name inside the quotes
    {X509Name.OU, "Infrastructure Team"},
    {X509Name.O, "Backbone (UK) Limited"}, //Organisation's Legal name inside the quotes
    {X509Name.L, "London"},
    {X509Name.ST, "England"},
    {X509Name.C, "GB"},
    };

    var subjectAlternateNames = new GeneralName[] { };

    var extensions = new Dictionary<DerObjectIdentifier, X509Extension>()
    {
    {X509Extensions.BasicConstraints, new X509Extension(true, new DerOctetString(new BasicConstraints(false)))},
    {X509Extensions.KeyUsage, new X509Extension(true, new DerOctetString(new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment | KeyUsage.DataEncipherment | KeyUsage.NonRepudiation)))},
    {X509Extensions.ExtendedKeyUsage, new X509Extension(false, new DerOctetString(new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth)))},
    };

    if (values[X509Name.CN].StartsWith("www.")) values[X509Name.CN] = values[X509Name.CN].Substring(4);

    if (!values[X509Name.CN].StartsWith("*.") && subjectAlternateNames.Length == 0)
    subjectAlternateNames = new GeneralName[] { new GeneralName(GeneralName.DnsName, $"www.{values[X509Name.CN]}") };

    if (subjectAlternateNames.Length > 0) extensions.Add(X509Extensions.SubjectAlternativeName, new X509Extension(false, new DerOctetString(new GeneralNames(subjectAlternateNames))));

    var subject = new X509Name(values.Keys.Reverse().ToList(), values);

    if (ecMode)
    {
    var gen = new ECKeyPairGenerator();
    //secp256r1 combined with SHA256withECDSA minimum recommended as per NIST RFC5480 to achieve 128bit encryption
    //secp384r1 combined with SHA384withECDSA message digest offers 192bit encryption
    //secp521r1 combined with SHA512withECDSA message digest offers 256bit encryption (browsers are not supporting this option right now)
    //browser cipher support can be checked via https://www.ssllabs.com/ssltest/viewMyClient.html
    var ecp = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256r1");
    gen.Init(new ECKeyGenerationParameters(new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H, ecp.GetSeed()), random));

    pair = gen.GenerateKeyPair();

    signatureFactory = new Asn1SignatureFactory("SHA256withECDSA", pair.Private);

    extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(false, new DerOctetString(new SubjectKeyIdentifierStructure(pair.Public))));
    csr = new Pkcs10CertificationRequest(signatureFactory, subject, pair.Public, new DerSet(new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(new X509Extensions(extensions)))), pair.Private);

    }
    else
    {
    var gen = new RsaKeyPairGenerator();
    gen.Init(new KeyGenerationParameters(random, 2048));

    pair = gen.GenerateKeyPair();

    signatureFactory = new Asn1SignatureFactory("SHA256withRSA", pair.Private);

    extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(false, new DerOctetString(new SubjectKeyIdentifierStructure(pair.Public))));
    csr = new Pkcs10CertificationRequest(signatureFactory, subject, pair.Public, new DerSet(new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(new X509Extensions(extensions)))), pair.Private);
    }

    //Convert BouncyCastle csr to .PEM file.
    var csrPem = new StringBuilder();
    var csrPemWriter = new PemWriter(new StringWriter(csrPem));
    csrPemWriter.WriteObject(csr);
    csrPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    csrPem.ToString().Dump("CSR");

    //Convert BouncyCastle Private Key to .PEM file.
    var privateKeyPem = new StringBuilder();
    var privateKeyPemWriter = new PemWriter(new StringWriter(privateKeyPem));
    privateKeyPemWriter.WriteObject(pair.Private);
    privateKeyPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    privateKeyPem.ToString().Dump("Private Key");

    //Convert BouncyCastle Private Key to .PEM file.
    var publicKeyPem = new StringBuilder();
    var publicKeyPemWriter = new PemWriter(new StringWriter(publicKeyPem));
    publicKeyPemWriter.WriteObject(pair.Public);
    publicKeyPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    publicKeyPem.ToString().Dump("Public Key");

    //Generate a self signed x509 certificate from above
    var notBefore = DateTime.UtcNow.Date;
    var certGenerator = new X509V3CertificateGenerator();

    certGenerator.SetSubjectDN(subject);
    certGenerator.SetIssuerDN(subject);
    certGenerator.SetNotBefore(notBefore);
    certGenerator.SetNotAfter(notBefore.AddYears(1).AddSeconds(-1));
    certGenerator.SetPublicKey(pair.Public);
    certGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random));

    foreach (var extension in extensions)
    certGenerator.AddExtension(extension.Key, extension.Value.IsCritical, extension.Value.GetParsedValue());

    var bouncyCert = certGenerator.Generate(signatureFactory);

    var store = new Pkcs12Store();
    var certificateEntry = new X509CertificateEntry(bouncyCert);
    store.SetCertificateEntry(subject.ToString(), certificateEntry);
    store.SetKeyEntry(subject.ToString(), new AsymmetricKeyEntry(pair.Private), new[] { certificateEntry });

    using (var stream = new MemoryStream())
    {
    var tempPassword = "password";
    store.Save(stream, tempPassword.ToCharArray(), random);
    using (var cert = new X509Certificate2(stream.ToArray(), tempPassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable))
    {
    StringBuilder builder = new StringBuilder();

    builder.AppendLine("-----BEGIN CERTIFICATE-----");
    builder.AppendLine(Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
    builder.AppendLine("-----END CERTIFICATE-----");

    builder.ToString().Dump("Self-signed Certificate");
    }
    }
    87 changes: 0 additions & 87 deletions csrgenerator.cs
    Original file line number Diff line number Diff line change
    @@ -1,87 +0,0 @@
    // this snippet can be easily used in any normal c# project as well by simply removing the .Dump() methods
    // and saving the output into a variable / file of your choice.
    // you'll need to add BouncyCastle.Crypto nuget to use this.
    // tested on 1.8.0-beta4

    using Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.Cms;
    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.OpenSsl;
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.X509.Extension;
    using System.IO;
    using System.Text;

    AsymmetricCipherKeyPair pair;
    Pkcs10CertificationRequest csr;

    var ecMode = false;
    var values = new Dictionary<DerObjectIdentifier, string> {
    {X509Name.CN, ""}, //domain name
    {X509Name.OU, "Domain Control Validated"},
    {X509Name.O, ""}, //Organisation's Legal name
    {X509Name.L, "London"},
    {X509Name.ST, "England"},
    {X509Name.C, "GB"},
    };

    var subjectAlternateNames = new GeneralName[] { };

    var extensions = new Dictionary<DerObjectIdentifier, X509Extension>()
    {
    {X509Extensions.BasicConstraints, new X509Extension(true, new DerOctetString(new BasicConstraints(false)))},
    {X509Extensions.KeyUsage, new X509Extension(true, new DerOctetString(new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment | KeyUsage.DataEncipherment | KeyUsage.NonRepudiation)))},
    {X509Extensions.ExtendedKeyUsage, new X509Extension(false, new DerOctetString(new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth)))},
    };

    if(values[X509Name.CN].StartsWith("www.")) values[X509Name.CN] = values[X509Name.CN].Substring(4);

    if (!values[X509Name.CN].StartsWith("*.") && subjectAlternateNames.Length == 0)
    subjectAlternateNames = new GeneralName[] { new GeneralName(GeneralName.DnsName, $"www.{values[X509Name.CN]}") };

    if (subjectAlternateNames.Length > 0) extensions.Add(X509Extensions.SubjectAlternativeName, new X509Extension(false, new DerOctetString(new GeneralNames(subjectAlternateNames))));

    var subject = new X509Name(values.Keys.Reverse().ToList(), values);

    if (ecMode)
    {
    var gen = new ECKeyPairGenerator();
    var ecp = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp384r1");
    gen.Init(new ECKeyGenerationParameters(new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H, ecp.GetSeed()), new SecureRandom()));

    pair = gen.GenerateKeyPair();

    extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(false, new DerOctetString(new SubjectKeyIdentifierStructure(pair.Public))));
    csr = new Pkcs10CertificationRequest("SHA256withECDSA", subject, pair.Public, new DerSet(new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(new X509Extensions(extensions)))), pair.Private);

    }
    else
    {
    var gen = new RsaKeyPairGenerator();
    gen.Init(new KeyGenerationParameters(new SecureRandom(), 2048));

    pair = gen.GenerateKeyPair();
    extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(false, new DerOctetString(new SubjectKeyIdentifierStructure(pair.Public))));
    csr = new Pkcs10CertificationRequest("SHA256withRSA", subject, pair.Public, new DerSet(new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(new X509Extensions(extensions)))), pair.Private);
    }

    //Convert BouncyCastle csr to .PEM file.
    var csrPem = new StringBuilder();
    var csrPemWriter = new PemWriter(new StringWriter(csrPem));
    csrPemWriter.WriteObject(csr);
    csrPemWriter.Writer.Flush();

    csrPem.ToString().Dump("CSR");

    var privateKeyPem = new StringBuilder();
    var privateKeyPemWriter = new PemWriter(new StringWriter(privateKeyPem));
    privateKeyPemWriter.WriteObject(pair.Private);
    csrPemWriter.Writer.Flush();

    privateKeyPem.ToString().Dump("Private Key");
  3. @venomed venomed revised this gist Sep 18, 2015. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions csrgenerator.cs
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    // this snippet can be easily used in any normal c# project as well by simply removing the .Dump() methods
    // and saving the output into a variable / file of your choice.
    // you'll need to add BouncyCastle.Crypto nuget to use this.
    // tested on 1.8.0-beta4

    @@ -75,14 +77,11 @@
    csrPemWriter.WriteObject(csr);
    csrPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    csrPem.ToString().Dump("CSR");

    //Convert BouncyCastle Private Key to .PEM file.
    var privateKeyPem = new StringBuilder();
    var privateKeyPemWriter = new PemWriter(new StringWriter(privateKeyPem));
    privateKeyPemWriter.WriteObject(pair.Private);
    csrPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    privateKeyPem.ToString().Dump("Private Key");
  4. @venomed venomed created this gist Sep 18, 2015.
    88 changes: 88 additions & 0 deletions csrgenerator.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    // you'll need to add BouncyCastle.Crypto nuget to use this.
    // tested on 1.8.0-beta4

    using Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.Cms;
    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.OpenSsl;
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.X509.Extension;
    using System.IO;
    using System.Text;

    AsymmetricCipherKeyPair pair;
    Pkcs10CertificationRequest csr;

    var ecMode = false;
    var values = new Dictionary<DerObjectIdentifier, string> {
    {X509Name.CN, ""}, //domain name
    {X509Name.OU, "Domain Control Validated"},
    {X509Name.O, ""}, //Organisation's Legal name
    {X509Name.L, "London"},
    {X509Name.ST, "England"},
    {X509Name.C, "GB"},
    };

    var subjectAlternateNames = new GeneralName[] { };

    var extensions = new Dictionary<DerObjectIdentifier, X509Extension>()
    {
    {X509Extensions.BasicConstraints, new X509Extension(true, new DerOctetString(new BasicConstraints(false)))},
    {X509Extensions.KeyUsage, new X509Extension(true, new DerOctetString(new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment | KeyUsage.DataEncipherment | KeyUsage.NonRepudiation)))},
    {X509Extensions.ExtendedKeyUsage, new X509Extension(false, new DerOctetString(new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth)))},
    };

    if(values[X509Name.CN].StartsWith("www.")) values[X509Name.CN] = values[X509Name.CN].Substring(4);

    if (!values[X509Name.CN].StartsWith("*.") && subjectAlternateNames.Length == 0)
    subjectAlternateNames = new GeneralName[] { new GeneralName(GeneralName.DnsName, $"www.{values[X509Name.CN]}") };

    if (subjectAlternateNames.Length > 0) extensions.Add(X509Extensions.SubjectAlternativeName, new X509Extension(false, new DerOctetString(new GeneralNames(subjectAlternateNames))));

    var subject = new X509Name(values.Keys.Reverse().ToList(), values);

    if (ecMode)
    {
    var gen = new ECKeyPairGenerator();
    var ecp = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp384r1");
    gen.Init(new ECKeyGenerationParameters(new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H, ecp.GetSeed()), new SecureRandom()));

    pair = gen.GenerateKeyPair();

    extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(false, new DerOctetString(new SubjectKeyIdentifierStructure(pair.Public))));
    csr = new Pkcs10CertificationRequest("SHA256withECDSA", subject, pair.Public, new DerSet(new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(new X509Extensions(extensions)))), pair.Private);

    }
    else
    {
    var gen = new RsaKeyPairGenerator();
    gen.Init(new KeyGenerationParameters(new SecureRandom(), 2048));

    pair = gen.GenerateKeyPair();
    extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(false, new DerOctetString(new SubjectKeyIdentifierStructure(pair.Public))));
    csr = new Pkcs10CertificationRequest("SHA256withRSA", subject, pair.Public, new DerSet(new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(new X509Extensions(extensions)))), pair.Private);
    }

    //Convert BouncyCastle csr to .PEM file.
    var csrPem = new StringBuilder();
    var csrPemWriter = new PemWriter(new StringWriter(csrPem));
    csrPemWriter.WriteObject(csr);
    csrPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    csrPem.ToString().Dump("CSR");

    //Convert BouncyCastle Private Key to .PEM file.
    var privateKeyPem = new StringBuilder();
    var privateKeyPemWriter = new PemWriter(new StringWriter(privateKeyPem));
    privateKeyPemWriter.WriteObject(pair.Private);
    csrPemWriter.Writer.Flush();

    //Push the csr Text to a Label on a Page
    privateKeyPem.ToString().Dump("Private Key");