Click here to Skip to main content
15,891,014 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
C#
<pre>using System;
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.Linq;
using System.Text;
using System.Collections.Generic;
using Org.BouncyCastle.Asn1.Microsoft;


namespace csrextension
{
    class Program
    {
        static void Main(string[] args)
        {
            
                // 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

                AsymmetricCipherKeyPair pair;
                Pkcs10CertificationRequest csr;

                var ecMode = true;
                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[] { };
                    string certificateTemplateName = "ZATCA-Code-Signing";
            X509ExtensionsGenerator extensionsGenerator = new X509ExtensionsGenerator();
            var micro = new Dictionary<MicrosoftObjectIdentifiers, DerObjectIdentifier>();

            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))));
            micro.Add(MicrosoftObjectIdentifiers.MicrosoftCertTemplateV1, false, (Asn1OctetString)new DerOctetString((Asn1Encodable)new DisplayText(2, certificateTemplateName)));

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

                if (ecMode)
                {
                    var gen = new ECKeyPairGenerator();
                    var ecp = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256k1");
                    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();

                Console.WriteLine(csrPem.ToString());

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

                //privateKeyPem.ToString().Dump("Private Key");
            }
        }
    }


What I have tried:

Hello,

I have this code to generate CSR ECDSA and want to add SANs, I can Add with GeneralName but don’t know how to add SerialNumber, Title, UID, registeredAddress, businessCategory and MicrosoftCertTemplateV1

Any help please?
Posted
Updated 3-Aug-22 20:15pm
v2

C#
IDictionary subjectAttributes = new Hashtable();
      subjectAttributes.Add(X509Name.C,countryName);
      subjectAttributes.Add(X509Name.OU,tinNumber);
      subjectAttributes.Add(X509Name.O,organizationName);
      subjectAttributes.Add(X509Name.CN,name);

      IDictionary subjectAlternativeNameAttributes = new Hashtable();




      subjectAlternativeNameAttributes.Add(X509Name.Surname,serialNumber);
      subjectAlternativeNameAttributes.Add(X509Name.UID,vatNumber);
      subjectAlternativeNameAttributes.Add(X509Name.T,invoiceType);
      subjectAlternativeNameAttributes.Add(RegisteredAddress,address);
      subjectAlternativeNameAttributes.Add(X509Name.BusinessCategory,businessCategory);




      var subjectName = new X509Name(new ArrayList(subjectAttributes.Keys),subjectAttributes);
      var subjectAltNames = new X509Name(new ArrayList(subjectAlternativeNameAttributes.Keys),subjectAlternativeNameAttributes);

      var generalNames = new GeneralNames(new[] { new GeneralName(subjectAltNames) });


      var extensionsGenerator = new X509ExtensionsGenerator();
      extensionsGenerator.AddExtension(MicrosoftObjectIdentifiers.MicrosoftCertTemplateV1,false,
          new DerOctetString(new DisplayText(4,"TSTZATCA-Code-Signing")));
      extensionsGenerator.AddExtension(X509Extensions.SubjectAlternativeName,false,generalNames);
      var extensions = extensionsGenerator.Generate();






      var signatureFactory = new Asn1SignatureFactory("SHA256WITHECDSA",keyPair.Private);



      var attribute = new Attribute(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(extensions));

      var requestAttributeSet = new DerSet(attribute);

      var certificateRequest =
          new Pkcs10CertificationRequest(signatureFactory, subjectName,keyPair.Public,requestAttributeSet);
 
Share this answer
 
You have to create DerObjectIdentifier object for that and use it

C#
DerObjectIdentifier regAddress = new DerObjectIdentifier("2.5.4.26");

IDictionary subjectAlternativeNameAttributes = new Hashtable();
subjectAlternativeNameAttributes.Add(regAddress, registeredAddress);
....
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900