Net - Httplistener With HTTPS Support - Stack Overflow
Net - Httplistener With HTTPS Support - Stack Overflow
Net - Httplistener With HTTPS Support - Stack Overflow
There seems to be a lot of confusing, sometimes conflicting, information with regards to making
a .NET HTTPListener HTTPS capable. My understanding is as follows:
58 One's C# code needs an https prefix (for example, https://*:8443 ) in order for the listener
to understand that it needs to service SSL requests at this port.
The actual SSL handshake happens under the covers and is handled by http.sys (buried
somewhere on the Windows machine). The C# code doesn't have to explicitly manage the
51 SSL handshake, because it happens under the covers.
One needs to have a "X.509 trusted certificate" on the httpListener machine, and
somehow that certificate needs to be bound to port 8443 (in this example).
Use makecert to create an X.509 certificate. This certificate gets stored in the personal
store and needs to get moved over to the Trusted Store (this is where the HTTP listener will
look). It seems I can use certMgr to perform the move, or I can use mmc to effect the move.
It seems there is more than one X.509 certificate format ( DER , Base64 , pks , pswd
protected, pks private, etc.)... Is there a preferred format I should use?
Once I get the certificate into the trusted store, I need to bind it to the TCP port. I am on
Windows 7: should I be using httpcfg or netsh ?
5 Answers
I did a bunch of homework and got this working. The steps to add SSL support for an .NET
HttpListener are:
81 1. Update C# application code to include the https prefix. Example:
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 1/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
The certhash is the thumbprint from your SSL certificate. You can find this using mmc.
The appid is found in Visual Studio...usually in assembly.cs, look for the GUID value.
There may be other ways to accomplish the above, but this worked for me.
Huh, I tried do to everything according to these hints but I cannot get through the last step - it says that
some param is not valid... – Moby04 Oct 12 '13 at 17:31
4 I've noticed when I copy-and-paste into the command line that sometimes a '?' appears between
"certhash=" and the actual key. Double-check you input. – jklemmack Dec 10 '13 at 21:28
1 Any way to chain a root CA cert to an intermediate certificate? – Hugh Jeffner Jun 16 '15 at 16:16
@WalterKelt Your answer helped me greatly, and filled in almost all of the blanks in the existing
documentation. However, there were a few I had to fill in myself, thus I posted my step-by-step process
as an answer. Cheers! – jpaugh Nov 25 '15 at 18:35
1 @WalterKelt just a guess, but probably the Guid in your AssemblyInfo file in the properties folder of the
executable project – Chris Klepeis Aug 11 '16 at 16:03
Here are the steps, in detail, that I followed to set up a stand-alone server on Windows, using
OpenSSL to create the self-signed certificate for a C# HTTPListener application. It includes
31 plenty of links, in case you want to do further research.
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 2/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
1. openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 , which will
prompt you for the value of each of the certificate's fields on the command line. For the
common name, type the domain name (e.g. localhost )
2. openssl pkcs12 -inkey bob_key.pem -in bob_cert.cert -export -out bob_pfx.pfx , so that it
can be imported with its key on the target machine.
*
For an alternative using makecert , see Walter's own answer.
3. Open Certificate Manager for the Local Machine. When you run certmgr.msc , it opens the
Certificate Manager for the current user, which is not what we want here. Instead:
1. From an administrative command prompt on the target machine, run mmc
4. In the dialog that appears, Choose Computer Account , and click Next
4. Import the certificate ( pfx ) into the Windows Certificate Store on the target machine
1. In the mmc window previously opened, drill down to
Certificates (Local Computer) > Personal
3. In the 2nd screen of the dialog that appears, find and import your certificate. You'll have
to change the file-type filter to Personal Information Exchange or All Files in order to
find it
4. On the next screen, enter the password you chose in step 2.1, and pay close attention
to the first check box. This determines how securely your certificate is stored, and also
how convenient it is to use
5. On the last screen, choose Place all certificates in the following store . Verify that it
says Personal , then click Finish
6. Repeat the import procedure above for the Trusted Root Certification Authorities
certificates section.
5. Create the port associations for your application. On Windows Vista and later, use netsh ,
as I did. (For Windows XP and earlier, use httpcfg )
From the administrative command line, type the following to set up the SSL binding* to
your app, and the appropriate port. NB: This command is easy to get wrong, because
(in PowerShell) the braces need to be escaped. The following PowerShell command
will work:
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
The ipport parameter will cause the SSL certificate to bind to the port 8443 on
our Terms of Service.
every network interface; to bind to a specific interface (only), choose the IP
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 3/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
@Jez IIRC, I didn't have an issue with using just the Trusted Root Certificate Authorities cert store.
Is there something special about your setup which requires the cert to be in the Personal store as well?
– jpaugh Feb 24 '16 at 16:38
When I ran the netsh command on the machine on which I'd installed the cert, I got the error "SSL
Certificate add failed, Error 1312 - A specified logon session does not exist. It may already have been
terminated." Looking at this answer to this question, it looks like the certificate is meant to be in the
Personal store to install it through netsh (it talks about running certutil with my rather than root ):
stackoverflow.com/a/19766650/178757 – Jez Feb 24 '16 at 16:40
Ok. Thanks for giving context for your edit. – jpaugh Feb 24 '16 at 19:21
4 On my Windows the command for generating the .pfx file hangs using Git-(Bash)-for-Windows. As a
solution, just add winpty before the command according to openssl-hangs-during-pkcs12-export. –
dwettstein Feb 23 '17 at 9:05
1 Thanks for your time, but I myself forgot when did I comment it, but I have upvoted your answer, so I
guess your answer worked for me, thanks:) – subha Jun 26 at 20:08
We can import the certificates using PowerShell and C# (no manual steps required).
/// <summary>
/// Create and install a self-signed certificate for HTTPS use
/// </summary>
private static void CreateInstallCert(int expDate, string password, string issuedBy)
{
// Create/install certificate
using (var powerShell = System.Management.Automation.PowerShell.Create())
{
var notAfter = DateTime.Now.AddYears(expDate).ToLongDateString();
var assemPath = Assembly.GetCallingAssembly().Location;
var fileInfo = new FileInfo(assemPath);
var saveDir = Path.Combine(fileInfo.Directory.FullName, "CertDir");
if (!Directory.Exists(saveDir))
{
Directory.CreateDirectory(saveDir);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
// This adds certificate to Personal and Intermediate Certification Authority
our Terms of Service
var. rootAuthorityName = "My-RootAuthority";
var rootFriendlyName = "My Root Authority";
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 4/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
var rootAuthorityScript =
$"$rootAuthority = New-SelfSignedCertificate" +
$" -DnsName '{rootAuthorityName}'" +
$" -NotAfter '{notAfter}'" +
$" -CertStoreLocation cert:\\LocalMachine\\My" +
$" -FriendlyName '{rootFriendlyName}'" +
$" -KeyUsage DigitalSignature,CertSign";
powerShell.AddScript(rootAuthorityScript);
powerShell.Invoke();
}
}
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
Requires PowerShell 4 or higher.
our Terms of Service.
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 5/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
answered Apr 14 at 17:48
Trevy Burgess
311 2 9
As making your own self signed certificates in the answers did not work for me and as the
question specifically calls for making a .net HTTPListener https capable and asks for any
1 tips/advice, I want to share my approach.You need a hostname, something like www.made-
up.com which needs to point to your WAN IP (e.g. ask your host provider for instructions) and
forward its port e.g. 443 to your local machine.Don't forget to open that inbound 443 port in your
firewall of your local machine.
1. Install IIS (via windows features on/of), create a website within IIS and assign the hostname.
Also make a secure (443 port) website of it.
2. Run letsencrypt-win-simple exe (I used version 1.9.1). Answer the questions to let it
generate the certificate.
3. After that you can stop de IIS server.
I believe you have to take note of the refresh task generated, since I am not sure it will succeed
after a few months (you probably have to start IIS again for the certificate to be renewed).
certbot works with cygwin and IIS, if you're able to add the "." -> "text/html" mime type. Do "pip3 install
certbot", then mount the web root into a standard posix path, then run "certbot certonly". Not the
smoothest, but it does work. – David Dombrowsky Nov 14 '18 at 1:58
Here is the full working code for HTTPListener on HTTPS (also works on LAN). To Generate the
Self Signed Certificate in C# using Bouncy Castle and Allow to access the URL on LAN.
1 NOTE: Don't forget to run as administrator.
Step 2: To access the URL over LAN, we need to add the firewall rule using power shell. Add
reference of System.Management.Automation.dll. Can be found in GAC.
using
By using our Org.BouncyCastle.Asn1;
site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
using Org.BouncyCastle.Asn1.Pkcs;
our Terms of Service.
using Org.BouncyCastle.Asn1.X509;
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 6/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace HTTPSListenerCode
{
class Program
{
_sslPort = 34443;
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 7/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
while (true)
{
try
{
IAsyncResult result = _listener.BeginGetContext(new
AsyncCallback(HttpListenerCallback), _listener);
Console.WriteLine("Waiting for request to be processed
asyncronously.");
result.AsyncWaitHandle.WaitOne(); //just needed to don't close this
thread, you can do other work or run in a loop
Console.WriteLine("Request processed asyncronously.");
}
}
}
//Process(context);
context.Response.ContentType = "text/html";
context.Response.ContentLength64 = bOutput2.Length;
Stream OutputStream2 = context.Response.OutputStream;
OutputStream2.Write(bOutput2, 0, bOutput2.Length);
OutputStream2.Close();
context.Response.StatusCode = (int)HttpStatusCode.OK;
if (cert == null)
{
throw new ArgumentNullException("Certificate");
}
var applicationId =
((GuidAttribute)typeof(Program).Assembly.GetCustomAttributes(typeof(GuidAttribute),
true)[0]).Value;
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 8/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
Console.WriteLine(ExecuteCommand("netsh http delete sslcert ipport=0.0.0.0:"
+ sslPort));
sslCert = ExecuteCommand("netsh http show sslcert 0.0.0.0:" + sslPort);
Console.WriteLine(sslCert);
return cert;
}
if (caCert == null)
{
return clientCert;
}
try
{
var certificates =
store.Certificates.Find(X509FindType.FindBySubjectName, subjectName, false);
if (certificates != null && certificates.Count > 0)
{
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
///log.Info("CHECK for X509 Certificate in localmachine certificate
our Terms of Service.
store = OK");
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 9/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
certificate = certificates[0];
}
}
catch (Exception ex)
{
}
return certificate;
// Serial Number
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One,
BigInteger.ValueOf(Int64.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);
// Signature Algorithm
const string signatureAlgorithm = "SHA256WithRSA";
certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = notBefore.AddYears(2);
certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
//
List<GeneralName> altNames = new List<GeneralName>();
altNames.Add(new GeneralName(GeneralName.IPAddress, "127.0.0.1"));
altNames.Add(new GeneralName(GeneralName.IPAddress, ipAddress));
altNames.Add(new
By using our site, you acknowledge GeneralName(GeneralName.DnsName,
that you domain));
have read and understand our Cookie Policy, Privacy Policy, and
altNames.Add(new GeneralName(GeneralName.DnsName, "localhost"));
our Terms of Service.
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 10/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
GeneralNames subjectAltNames = GeneralNames.GetInstance(new
DerSequence((GeneralName[])altNames.ToArray()));
certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName,
false, subjectAltNames);
//
// selfsign certificate
Org.BouncyCastle.X509.X509Certificate certificate =
certificateGenerator.Generate(issuerPrivKey, random);
Asn1Sequence seq =
(Asn1Sequence)Asn1Object.FromByteArray(info.ParsePrivateKey().GetDerEncoded());
if (seq.Count != 9)
{
//throw new PemException("malformed sequence in RSA private key");
}
rsaProvider.ImportParameters(parameters);
return rsaProvider;
}
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 11/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
// Serial Number
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One,
BigInteger.ValueOf(Int64.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);
// Signature Algorithm
const string signatureAlgorithm = "SHA256WithRSA";
certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = notBefore.AddYears(2);
certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
// selfsign certificate
Org.BouncyCastle.X509.X509Certificate certificate =
certificateGenerator.Generate(issuerKeyPair.Private, random);
X509Certificate2 x509 = new
System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
CaPrivateKey = issuerKeyPair.Private;
return x509;
//return issuerKeyPair.Private;
static bool
addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert,
System.Security.Cryptography.X509Certificates.StoreName st,
System.Security.Cryptography.X509Certificates.StoreLocation sl)
{
bool bRet = false;
try
{
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
X509Store store = new X509Store(st, sl);
our Terms of Service.
store.Open(OpenFlags.ReadWrite);
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 12/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow
store.Add(cert);
store.Close();
}
catch
{
return bRet;
}
return stringBuilder.ToString();
}
}
}
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
our Terms of Service.
https://stackoverflow.com/questions/11403333/httplistener-with-https-support 13/13