Sometimes we just need to run kestrel without the need for a green browser padlock and therefor not needing to have a “real” certificate. but still want secure HTTPS communications on the APIs.
Here we will create a simple method you can drop in to generate a valid self-signed certificate on the fly to use in Kestrel on any port of your choice!
In our Program.cs we have the following method where we want to now manually configure Listen Options.
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>() // Add UseKestrel to control it's options .UseKestrel(options => { // http:localhost:5000 options.Listen(IPAddress.Loopback, 5000); // https:localhost:5001 options.Listen(IPAddress.Loopback, 5001); // http:*:80 options.Listen(IPAddress.Any, 80); // https:*:443 options.Listen(IPAddress.Any, 443, listenOptions => { listenOptions.UseHttps(GetSelfSignedCertificate()); }); }); });
As you can see on line 15 we have a method called GetSelfSignedCertificate() Now we need to add this method to Program.cs or anywhere else you see fit:
private static X509Certificate2 GetSelfSignedCertificate() { var password = Guid.NewGuid().ToString(); var commonName = "MyCommonName"; var rsaKeySize = 2048; var years = 5; var hashAlgorithm = HashAlgorithmName.SHA256; using (var rsa = RSA.Create(rsaKeySize)) { var request = new CertificateRequest($"cn={commonName}", rsa, hashAlgorithm, RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add( new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false) ); request.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension( new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false) ); var certificate = request.CreateSelfSigned(DateTimeOffset.Now.AddDays(-1), DateTimeOffset.Now.AddYears(years)); certificate.FriendlyName = commonName; // Return the PFX exported version that contains the key return new X509Certificate2(certificate.Export(X509ContentType.Pfx, password), password, X509KeyStorageFlags.MachineKeySet); }
When your application starts up it will enable kestrel to serve on the defined ports and generate a new certificate on the fly and serve your API endpoints securly using HTTPs.
Enjoy 😊
Thank you very much! This is exactly what I was looking for!
P.S. There is a small mistake in “opt” and “options” variable but is an easy fix.
Hi Calin,
Thank you very much for your comment.
You are correct, I have corrected the variable naming in the example. 🙂
Thanks Niels for your example.
I must admit I’ve tried numerous ways to get a local RPI4 (as well as my Win machine) to just present a web page without that annoying initial message from Chrome “Your connection is not private”.
However, trying your example I still get that. A green padlock would obviously be nice, but just getting rid of that cert is invalid message would be great.
I’ve tried on Chromium v99 (Chrome and Edge) on my Windows 10 machine using VS2022.
What can I be doing wrong?
King regards
Magnus
Lund, Sweden
NET::ERR_CERT_AUTHORITY_INVALID
Subject: MyCommonName
Issuer: MyCommonName
Expires on: Mar 22, 2027
Current date: Mar 22, 2022
PEM encoded chain:
—–BEGIN CERTIFICATE—–
MIIC1DCCAbygAwIBAgIIfO/GRjHJd4kwDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UE
AxMMTXlDb21tb25OYW1lMB4XDTIyMDMyMTA5MjU0NloXDTI3MDMyMjA5MjU0Nlow
FzEVMBMGA1UEAxMMTXlDb21tb25OYW1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAtnu5gl3uxNFxk43h51FzdVhQxO0Ds4EqZpb9R1R7HV4PHLIHMvcf
gHjLr9iGmWPllQa5Ci0kqhY01W5lUPYjAtgdn43FsbVj46o98tUQWnH64VKrX5LR
YlijL1E+dq4TDXvUYI3muMsPaO7kt0lqEt9ZcO7IjPCpjWdc/xAK9k5dP1Jo3SmI
JlP99YzL6SRHFlakO7Im6pyodCj2hJe6Bp2fzH908Jhp7Rmueqib2WBWiP+ziDzx
4gN4ChyICBZjQdouf8Vp+f4jEIuGYDFM5bEt5afFACQtxAC95v/CNCU3157B4bnR
OyoQVLnZuEo63kNwNr1J1ldO6vMtzOQSbQIDAQABoyQwIjALBgNVHQ8EBAMCBLAw
EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAGP+az8mftRV
kiJkmyTPJjjH6utqmobtojB+gvuijxLJyrvnLSCbQSDtQbVznXuqI1qTVJBvqPto
UBCUlfe6Cv4nvaPOwNB6cWqidgw/6MbEP8liiTVjRVeUz3iO5Rasjf9WGdLc9sTN
FYbGCQn4A+OsqQ/6Vz5QS3xrNynqU1rAxygeT9KlVJy7cfAHIBpz2waRhfDiML3E
oFv4j13ro6JlcS+rCXmI5XXfgMuNxvcanTz9xMi7hpOF3p0rJNSj3F7J5ljsZGbV
sdn+sxkjG3TmeTBDLJLyU37Nuqx9eJ1KfY3vrjqNIfbCACoYh7NK/o3PC8pH/L48
Muw3Ybstxl0=
—–END CERTIFICATE—–
Hi Magnus,
Thank you for your comment 🙂
There is no way unfortunately for you to get a green browser with these certificates, as they are not signed by a CA and are generated on every startup so you cannot even save it to your PC.
This is meant mostly for scenarios where you either do not have a purchased valid certificate or you are unable to use a service like Let’s Encrypt to generate and renew certificates.
I personally only use this for API calls where there is no browser warnings but I would like to use SSL. This still means your code has to except “invalid” certificates for it to work.
Hope this sheds some light on your question.
Kind regards
Niels
Thank you very much. I was looking for such a solution for a while. I was afraid I had to use an official certificate for my internal app only. This helps a lot!
Regards
Patrick
Hi Patrick,
That is awesome, so glad this helped you out 🙂
Dude! Thanks so much – I was using ECdsa and I did *something* wrong and kept getting SCHANNEL errors – but your code works like a charm. Much appreciated!
Hi Andrew,
Thank you so much man I really appreciate you took the time to comment, and I am thrilled it helped you out 🙂
Good luck with you project