Whenever I get some free time I like to tackle certain projects that have piqued my interest. Often times I don’t get to complete these projects, or they take months to complete. In this case I’ve spent the last few months trying to get these samples to work. Hopefully you’ll find them useful.

In the world of security, and more specifically in .NET, there aren’t a whole lot of options for creating certificates for development. Sure you could use makecert.exe or if you’re truly masochistic you could spin up a CA, but both are a pain to use and aren’t necessarily useful when you need to consistently create signed certificates for whatever reason. Other options include using a library like BouncyCastle but that can be a bit complicated, and given the portable nature of the library, doesn’t use Windows APIs to do the work.

So I offer some sample code. This code should not be used in production. Please. Seriously. It’s not that good. Its great for testing, but its in no shape whatsoever for production systems. That’s why CAs are built.

In any case I’ve put the code up on Github. There is no license so use it as you see fit so long as it doesn’t come back to bite me in the ass.

This gist shows how you can create self-signed certificates and how you can then sign the certificates of those keys with a CA’s private key. The calling code is in the KeyGenSigning project, and the actual meat of the signing is done in the CertLib project. The key generation and signing bits are mostly P/Invoke’d APIs so they execute fairly fast.

Currently the code relies on CSPs to do the work. In theory it could work with NCryptoKey’s but I haven’t tried it yet.

In any case, enjoy. Hopefully you found this useful.

8 Comments

  1. Shyam Gopi

    I am trying to create a self-signed certificate chain which should have the following 2 certificates:
    1. Root cert.
    2. Cert1 signed using root cert with certificate template as CEPEncryption.

    In your example, Cert1 is a sub-ordinate cert. The only problem is that I need Cert1 to be of a particular template instead of being a sub-ordinate cert. Is this possible? If so, how?

    Reply
  2. Brendan Stewart

    CertLib isn’t present on Windows 10 machines. Nor does it appear to be a package i can get.

    Reply
  3. Brendan Stewart

    Nevermind, found your whole solution on Github

    Reply
  4. Brendan Stewart

    I do have one question though, where in the code does one set to include the private key for the subordinate certificate?

    Reply
    • This only produces a key for validation; apparently, IIS doesn’t encrypt using the client certificate(?), so apparently the author didn’t find this necessary.
      You can use CertLib.CertificateSigner.SignCertificate() (called by SignIt called by KeyGenSigning Main) to sign an arbitrary CertLib.CertificateSigningRequest using an arbitrary CA cert.

      I do wonder, though, why the OIDs don’t propagate properly into the signed certificate, making it unusable for client authentication – it seems the methods invoked by CertLib.CertificateSigner.SignCertificate are buggy, but I’m no programmer so finding it hard to properly debug…

      Reply
      • Steve Syfuhs

        The subordinate private key is unrelated to the signing process, so it’s left to the reader to figure out how to re-associate — the simplest approach is to just set the subordinate cert’s private key property:

        X509Certificate2 unsignedSub = GenerateOrLoadWithPrivateKeyOrWhatever();

        X509Certificate2 signed = Sign(unsignedSub);
        signed.PrivateKey = unsignedSub.PrivateKey;

        signed.Export(…as pfx…)
        // or
        X509Store store = new X509Store(…);
        store.Add(signed);

        Reply
        • Patryk

          Hi!
          According to your clues, I set extensions in request.Extensions, so subordinateCertInfo.cExtension and subordinateCertInfo.rgExtension are set.
          Unfortunately after calling NativeMethods.CryptSignAndEncodeCertificate and after var sginedCert = new X509Certificate2(pbEncodedCert) the certificate still doesn’t have Extensions 🙁 I have no idea what’s the cause and how to resolved it.
          I hope you could help me with this issue. Thanks in advance!

          Reply

Join the conversation