Search code examples
c#bouncycastle

Specify certificate template in certificate request using BouncyCastle


I'm using BouncyCastle to generate a certificate request:

using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using System.IO;

class Program {
    static void Main(string[] args) {
        var keyGenerator = new RsaKeyPairGenerator();
        keyGenerator.Init(
            new KeyGenerationParameters(
                new SecureRandom(new CryptoApiRandomGenerator()),
                2048));
        var keyPair = keyGenerator.GenerateKeyPair();
        X509Name name = new X509Name("CN=test");
        Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA256WITHRSA", name, keyPair.Public, null, keyPair.Private);
        using (FileStream fs = new FileStream(@"X:\tmp\tmp.csr", FileMode.Create)) {
            var req = csr.GetDerEncoded();
            fs.Write(req, 0, req.Length);
        }
    }
}

How should I specify the certificate template in the request?

Note: decoding a request created with the certificates console using certutil, it looks like the certificate template should be an extension of the request; I tried creating an extension accordingly:

var extGen = new Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator();
extGen.AddExtension(
    new DerObjectIdentifier("1.3.6.1.4.1.311.21.7"), // OID for certificate template extension 
    true,
    new DerObjectIdentifier("1.3.6.1.4.1.311.21.8.the.OID.of.the.template"));

But then, I don't understand how I'm supposed to attach it to the request.


Solution

  • After some digging, this solution seems to work:

    const string TemplateOid = "1.3.6.1.4.1.311.21.8.etc.etc";
    const int MajorVersion = 100;
    const int MinorVersion = 4;
    
    Dictionary<DerObjectIdentifier, X509Extension> extensionsDictionary = new Dictionary<DerObjectIdentifier,X509Extension>();
    DerObjectIdentifier certificateTemplateExtensionOid = new DerObjectIdentifier("1.3.6.1.4.1.311.21.7");
    DerSequence certificateTemplateExtension = new DerSequence(
        new DerObjectIdentifier(TemplateOid),
        new DerInteger(MajorVersion),
        new DerInteger(MinorVersion));
    extensionsDictionary[certificateTemplateExtensionOid] = new X509Extension(
        false,
        new DerOctetString(certificateTemplateExtension));
    X509Extensions extensions = new X509Extensions(extensionsDictionary);
    Attribute attribute = new Attribute(
        PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
        new DerSet(extensions));
    DerSet attributes = new DerSet(attribute);
    Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA256WITHRSA", name, keyPair.Public, attributes, keyPair.Private);