Creating self-signed X.509 (SSL) certificates in .NET using Mono.Security

***Disclaimer***

I’m not a security expert. For that reason, I’m not completely sure in what kind of situations you can use this solution, but you should probably not use it for any production purposes. If you are an expert, please let me know if there are any problems (or not) with the solution.

*** End disclaimer ***

I recently had to programmatically create self-signed X.509 certificates in a .NET application for my WadGraphEs Azure Dashboard project. Specifically, I wanted to generate a PCKCS#12 .pfx file containing the private key and the certificate, as well as a DER .cer file containing the certificate file only.

Unfortunately there doesn’t seem to be an out of the box managed API available from Microsoft, but I was able to make it work using Mono.Security. To see how it’s done, let’s start how to generate them with makecert.exe in the first place.

Creating a self-signed certificate using makercert.exe

makecert.exe is a Microsoft tool that you can use to create self-signed certificates. It’s documented here, and the basic syntax to create a self signed certificate is:

makecert -sky exchange -r -n "CN=certname" -pe -a sha1 -len 2048 -ss My "certname.cer"

This will do a couple of things:

  • Generate a 2048 bit long private/public exchange type key pair
  • Generate a certificate with name “CN=certname” and signed with above-mentioned keys
  • Store the certificate + private key in the “My” certificate store
  • Store the DER format certificate only in the file “certname.cer”

So the .cer file containing the certificate is already generated using this method, and we can get to the .pfx file by exporting it (Copy to file…) from certmgr.msc.

Now, the problem is we can’t easily do this from code. I specifically needed a managed solution, so invoking makecert.exe from my application wouldn’t do it, and neither would using the Win32 APIs. Luckily, the Mono guys actually created a managed makecert.exe port, so with a bit of tuning it should actually be possible to generate the certificate.

Mono.Security to the rescue

The code to the makecert port is available at https://github.com/mono/mono/blob/master/mcs/tools/security/makecert.cs. To use it to generate the self-signed certificate I extracted the code that’s actually used given the provided command line parameters above, and put that into its own class:

Generating a .pfx and .cer is now done as follows (once you’ve nuget installed Mono.Security):

And that’s it, you have now created a pfx/cer pair from pure managed code.

Closing remarks on Mono.Security

There are a couple of peculiarities with the makecert port:

  • The tool initializes CspParameters subjectParams and CspParameters issuerParameters based on the command line arguments, but it does not actually seem to be using them when generating the certificate. I don’t think our set of command line parameters actually influences those two objects, but it’s still a little bit weird.
  • The tool doesn’t support the -len parameter, so I’ve changed the way to generate the key by not using the RSA.Create() factory, but instead hard-code it to new RSACryptoServiceProvider(2048), which should do it. I’ve also confirmed the length using both OpenSSL and certmgr.msc.

It’d be great if someone can independently verify whether the above two points are indeed working as intended.

Anyway, big thanks to the Mono.Security team for providing the makecert port.