16

I want to use HTTPS in my ASP.Net Core 2.0 (with Kestrel web server) application.

The official documentation uses pfx format, but I want to use PEM format (generated from Let's encrypt) directly without any conversion (at least nothing outside my C# code). Is is possible?

Mohammed Noureldin
  • 14,913
  • 17
  • 70
  • 99
  • you could try one of the answers from https://stackoverflow.com/questions/7400500/how-to-get-private-key-from-pem-file though I'd have thought it easier just to convert the certicate with the openssl command line tool – junichiro Jan 03 '18 at 13:12
  • 2
    Use command openssl pkcs12 -inkey privkey.pem -in cert.pem -export -out cert_pfx.pfx Then you will be prompt for password. Copy cert_pfx.pfx at dotnet publish folder and finally in Program.cs change: .UseKestrel(options => { options.Listen(IPAddress.Any, 3000, listenOptions => { listenOptions.UseHttps("cert_pfx.pfx", "selected password"); }); //https } ) – David Soler Nov 07 '18 at 15:13
  • 1
    For anyone new around, see https://www.scottbrady91.com/C-Sharp/PEM-Loading-in-dotnet-core-and-dotnet – Mugen Nov 04 '20 at 17:54

3 Answers3

7

The short answer is that you can't. At least, you can't without a whole lot of work or using something like Bouncy Castle.

When the cert and the key are put together into a PFX the X509Certificate2 object will have cert.HasPrivateKey == true, and is capable of using the private key via the Get[Algorithm]PrivateKey extension method family. When you load a PEM certificate only the public certificate portion is loaded (and if it's a PEM certificate with a PEM key glued onto it? That's still just a PEM certificate).

The easy way to get a private key associated with a certificate is with the new (in .NET Core 2.0) certWithKey = cert.CopyWithPrivateKey(key) extension method family. So now you "just" need to load the private key. .NET does not currently have the ability to load (or save) ".key" files (no matter what their extension). If you want to take a crack at loading one you might want to check some prior art:

The good news is that .NET is planning to support loading keys in the future (https://github.com/dotnet/corefx/issues/20414), but since it isn't done yet (much less released) that doesn't help you right now.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
  • 3
    FWIW won't be available until .NET Core 3.0 per the github issue – Chris Marisic Sep 25 '18 at 15:33
  • 3
    For future reference, .NET Core 3.0 includes the final API https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#cryptographic-key-importexport – Lex Li Aug 31 '19 at 17:17
6

For those that find this, and are using dotnet 5+

var pem = File.ReadAllText("path/to/my.pem");
var key = X509Certificate2.CreateFromPem(pem);

If you need the private + public,

var certPem = File.ReadAllText("path/to/fullchain.pem");
var keyPem = File.ReadAllText("path/to/privkey.pem");
var x509 = X509Certificate2.CreateFromPem(certPem, keyPem);

This can then be hooked into Kestrel like this:

webApplicationBuilder.WebHost.ConfigureKestrel(s => {
    s.ListenAnyIP(443, options => {
        options.UseHttps(x509);
    }

And maybe also look at https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet

Iain Ballard
  • 4,433
  • 34
  • 39
4

ASP.NET 5 introduced appsettings for configuring PEM crt/key for the default cert:

{
  "Kestrel": {
    "Certificates": {
      "Default": {
        "Path": "<path to .pem/.crt file>",
        "KeyPath": "<path to .key file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

Note that the paths are relative to your bin directory, but can also be absolute. They do not support environment variables or ~.

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-7.0#replace-the-default-certificate-from-configuration

carlin.scott
  • 6,214
  • 3
  • 30
  • 35