Net - Httplistener With HTTPS Support - Stack Overflow

Download as pdf or txt
Download as pdf or txt
You are on page 1of 13

29/10/2019 .

net - Httplistener with HTTPS support - Stack Overflow

Httplistener with HTTPS support


Asked 7 years, 3 months ago Active 30 days ago Viewed 58k times

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).

Is my understanding above correct? If not, please educate me.

Regarding X.509 certificates, my understanding is:

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 ?

.net x509certificate httplistener

edited Apr 23 at 13:21 asked Jul 9 '12 at 21:19


Peter Mortensen Walter Kelt
14.6k 19 89 118 1,264 1 12 20

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:

String[] prefixes = { "http://*:8089/","https://*:8443/" };

That's it from the code aspect.


2. For the certificate side of things, using a Windows SDK command console (can also use
the you
By using our site, Visual Studio Professional
acknowledge command
that you have console) our Cookie Policy, Privacy Policy, and
read and understand
our Terms of Service.
Use makecert.exe to create a certificate authority. Example:

https://stackoverflow.com/questions/11403333/httplistener-with-https-support 1/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow

makecert -n "CN=vMargeCA" -r -sv vMargeCA.pvk vMargeCA.cer

Use makecert.exe to create an SSL certificate

makecert -sk vMargeSignedByCA -iv vMargeCA.pvk -n "CN=vMargeSignedByCA" -ic


vMargeCA.cer vMargeSignedByCA.cer -sr localmachine -ss My

Use MMC GUI to install CA in Trusted Authority store


Use MMC GUI to install an SSL certificate in Personal store
Bind certificate to IP address:port and application. Example:

netsh http add sslcert ipport=0.0.0.0:8443


certhash=585947f104b5bce53239f02d1c6fed06832f47dc appid={df8c8073-5a4b-4810-b469-
5975a9c95230}

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.

edited Apr 23 at 13:09 answered Jul 12 '12 at 17:55


Peter Mortensen Walter Kelt
14.6k 19 89 118 1,264 1 12 20

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.

1. Create a stand-alone server in .NET via HttpListener :

var prefixes = {"http://localhost:8080/app/root", "https://localhost:8443/app/root"};


var listener = new HttpListener();
foreach (string s in prefixes)
listener.Prefixes.Add(s);
listener.Start();
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and
our Terms 2. Service.self-signed certificate:*
of Create

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

2. Press Ctrl + M , or Click File > Add/Remove Snap-in

3. Choose Certificates , and click Add >

4. In the dialog that appears, Choose Computer Account , and click Next

5. Choose Local Computer . Click Finish , then Okay

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

2. Right-click on Personal , then click on All Tasks -> Import...

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:

netsh http add sslcert ipport=0.0.0.0:8443 `


certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 `
appid=`{00112233-4455-6677-8899-AABBCCDDEEFF`}

For cmd.exe , the following should be used instead:

netsh http add sslcert ipport=0.0.0.0:8443


certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-
AABBCCDDEEFF}

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

address associated with that network interface.


The certhash is simply the certificate thumbprint, with spaces removed
The appid is the GUID stored in the Assembly Info of your application. (Sidenote:
The netsh mechanism is evidently a COM interface, judging from this question
and its answers)
*
Microsoft has redirected the SSL Binding link from here to there.
6. Start up your web-server, and you're good to go!

edited Apr 23 at 13:31 answered Nov 24 '15 at 22:23


Peter Mortensen jpaugh
14.6k 19 89 118 4,223 3 26 70

@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).

For details, see: https://blog.davidchristiansen.com/2016/09/howto-create-self-signed-


2 certificates-with-powershell/

I'm using this code:

/// <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);

// Export CRT file


var rootAuthorityCrtPath = Path.Combine(saveDir, "MyRootAuthority.crt");
var exportAuthorityCrtScript =
$"$rootAuthorityPath = 'cert:\\localMachine\\my\\' +
$rootAuthority.thumbprint;" +
$"Export-Certificate" +
$" -Cert $rootAuthorityPath" +
$" -FilePath {rootAuthorityCrtPath}";
powerShell.AddScript(exportAuthorityCrtScript);

// Export PFX file


var rootAuthorityPfxPath = Path.Combine(saveDir, "MyRootAuthority.pfx");
var exportAuthorityPfxScript =
$"$pwd = ConvertTo-SecureString -String '{password}' -Force -AsPlainText;" +
$"Export-PfxCertificate" +
$" -Cert $rootAuthorityPath" +
$" -FilePath '{rootAuthorityPfxPath}'" +
$" -Password $pwd";
powerShell.AddScript(exportAuthorityPfxScript);

// Create the self-signed certificate, signed using the above certificate


var gatewayAuthorityName = "My-Service";
var gatewayFriendlyName = "My Service";
var gatewayAuthorityScript =
$"$rootcert = ( Get-ChildItem -Path $rootAuthorityPath );" +
$"$gatewayCert = New-SelfSignedCertificate" +
$" -DnsName '{gatewayAuthorityName}'" +
$" -NotAfter '{notAfter}'" +
$" -certstorelocation cert:\\localmachine\\my" +
$" -Signer $rootcert" +
$" -FriendlyName '{gatewayFriendlyName}'" +
$" -KeyUsage KeyEncipherment,DigitalSignature";
powerShell.AddScript(gatewayAuthorityScript);

// Export new certificate public key as a CRT file


var myGatewayCrtPath = Path.Combine(saveDir, "MyGatewayAuthority.crt");
var exportCrtScript =
$"$gatewayCertPath = 'cert:\\localMachine\\my\\' + $gatewayCert.thumbprint;"
+
$"Export-Certificate" +
$" -Cert $gatewayCertPath" +
$" -FilePath {myGatewayCrtPath}";
powerShell.AddScript(exportCrtScript);

// Export the new certificate as a PFX file


var myGatewayPfxPath = Path.Combine(saveDir, "MyGatewayAuthority.pfx");
var exportPfxScript =
$"Export-PfxCertificate" +
$" -Cert $gatewayCertPath" +
$" -FilePath {myGatewayPfxPath}" +
$" -Password $pwd"; // Use the previous password
powerShell.AddScript(exportPfxScript);

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.

I used https://letsencrypt.org/. On windows this not as easy as on Linux because there is no


official certbot ACME client for windows. However you can use https://github.com/Lone-
Coder/letsencrypt-win-simple, of which there are also binaries around. However "Currently only
IIS is supported". But you can easily trick it to create a certificate on your computer such that you
can approach your httplistener the SSL way:

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).

edited Dec 27 '16 at 20:46 answered Dec 27 '16 at 20:39


Stefan Verhagen
128 2 6

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 1: Install Bouncy Castle Pacakge:

Install-Package BouncyCastle -Version 1.8.5

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.

Step 3: Full Code

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
{

static int _sslPort;


static Thread _serverThread;
static HttpListener _listener;

static void Main()


{

_sslPort = 34443;

string certificateSubjectName = "MyCertificate";


var cert = CreateInstallCert(_sslPort, certificateSubjectName,
GetLocalIPAddress(), "*.domain.com");
InitializeHTTPListner();

string url = "https://localhost:" + _sslPort.ToString();


System.Diagnostics.Process.Start(url);

static void InitializeHTTPListner()


{
//Need to Firewall rule to access the IP in LAN
//Add refernce to
C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf

var powershell = PowerShell.Create();


var psCommand = $"New-NetFirewallRule -DisplayName \"My HTTP Listener Print
Server\" -Direction Inbound -LocalPort {_sslPort} -Protocol TCP -Action Allow";
powershell.Commands.AddScript(psCommand);
powershell.Invoke();
_serverThread = new Thread(HTTPListen);
_serverThread.Start();
}

static void HTTPListen()


{
_listener = that
By using our site, you acknowledge new you
HttpListener();
have read and understand our Cookie Policy, Privacy Policy, and
_listener.Prefixes.Add("https://*:" + _sslPort.ToString() + "/");
our Terms of Service.
_listener.Start();

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.");

//HttpListenerContext context = _listener.GetContext();


//Process(context);
}
catch (Exception ex)
{

}
}
}

static void HttpListenerCallback(IAsyncResult result)


{
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);

//Process(context);

var html = $"<html><body><h1>HTTP Listener is working</h1></body></html>";

byte[] bOutput2 = System.Text.Encoding.UTF8.GetBytes(html);

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;

static X509Certificate2 CreateInstallCert(int sslPort, string subjectName,


string ipAddress, string domain)
{
X509Certificate2 cert = CheckAndGenerate(subjectName, ipAddress, domain);

if (cert == null)
{
throw new ArgumentNullException("Certificate");
}

var applicationId =
((GuidAttribute)typeof(Program).Assembly.GetCustomAttributes(typeof(GuidAttribute),
true)[0]).Value;

var sslCert = ExecuteCommand("netsh http show sslcert 0.0.0.0:" + sslPort);


if (sslCert.IndexOf(cert.Thumbprint, StringComparison.OrdinalIgnoreCase) >=
0)
{
if (sslCert.IndexOf(applicationId, StringComparison.OrdinalIgnoreCase)
>= 0)
{
return cert;
}
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 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);

if (sslCert.IndexOf(applicationId, StringComparison.OrdinalIgnoreCase) >= 0)


{
Console.WriteLine("This implies we can start running.");
Console.WriteLine(ExecuteCommand("netsh http delete sslcert
ipport=0.0.0.0:" + sslPort));
}

Console.WriteLine(ExecuteCommand($"netsh http add sslcert ipport=0.0.0.0:


{sslPort} certhash={cert.Thumbprint} appid={{{applicationId}}}"));

return cert;
}

static X509Certificate2 CheckAndGenerate(string subjectName, string ipAddress,


string domain)
{
AsymmetricKeyParameter caPrivateKey = null;

string subjectCAName = subjectName + "CA";

var caCert = CheckIfCertificateExists(subjectCAName, StoreName.Root,


StoreLocation.LocalMachine);
var clientCert = CheckIfCertificateExists(subjectName, StoreName.My,
StoreLocation.LocalMachine);

if (caCert == null)
{

caCert = GenerateCACertificate("CN=" + subjectCAName, ref caPrivateKey);


addCertToStore(caCert, StoreName.Root, StoreLocation.LocalMachine);
if (clientCert == null)
{
clientCert = GenerateSelfSignedCertificate("CN=" + subjectName,
"CN=" + subjectCAName, caPrivateKey, ipAddress, domain);
var p12 = clientCert.Export(X509ContentType.Pfx);
addCertToStore(new X509Certificate2(p12, (string)null,
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet), StoreName.My,
StoreLocation.LocalMachine);
addCertToStore(new X509Certificate2(p12, (string)null,
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet), StoreName.Root,
StoreLocation.LocalMachine);
}

return clientCert;
}

static X509Certificate2 CheckIfCertificateExists(string subjectName, StoreName


storeName, StoreLocation storeLocation)
{
X509Store store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 certificate = null;

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;

static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string


issuerName, AsymmetricKeyParameter issuerPrivKey, string ipAddress, string domain)
{
const int keyStrength = 2048;

// Generating Random Numbers


CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);

// The Certificate Generator


X509V3CertificateGenerator certificateGenerator = new
X509V3CertificateGenerator();

// 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);

// Issuer and Subject Name


X509Name subjectDN = new X509Name(subjectName);
X509Name issuerDN = new X509Name(issuerName);
certificateGenerator.SetIssuerDN(issuerDN);
certificateGenerator.SetSubjectDN(subjectDN);

// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = notBefore.AddYears(2);

certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);

// Subject Public Key


AsymmetricCipherKeyPair subjectKeyPair;
var keyGenerationParameters = new KeyGenerationParameters(random,
keyStrength);
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
subjectKeyPair = keyPairGenerator.GenerateKeyPair();

certificateGenerator.SetPublicKey(subjectKeyPair.Public);

// Generating the Certificate


AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

//
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);

// correcponding private key


PrivateKeyInfo info =
PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);

// merge into X509Certificate2


X509Certificate2 x509 = new
System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

Asn1Sequence seq =
(Asn1Sequence)Asn1Object.FromByteArray(info.ParsePrivateKey().GetDerEncoded());
if (seq.Count != 9)
{
//throw new PemException("malformed sequence in RSA private key");
}

RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);


RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1,
rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);

x509.PrivateKey = ToDotNetKey(rsaparams); //x509.PrivateKey =


DotNetUtilities.ToRSA(rsaparams);
return x509;

static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)


{
var cspParams = new CspParameters
{
KeyContainerName = Guid.NewGuid().ToString(),
KeyNumber = (int)KeyNumber.Exchange,
Flags = CspProviderFlags.UseMachineKeyStore
};

var rsaProvider = new RSACryptoServiceProvider(cspParams);


var parameters = new RSAParameters
{
Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
P = privateKey.P.ToByteArrayUnsigned(),
Q = privateKey.Q.ToByteArrayUnsigned(),
DP = privateKey.DP.ToByteArrayUnsigned(),
DQ = privateKey.DQ.ToByteArrayUnsigned(),
InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
D = privateKey.Exponent.ToByteArrayUnsigned(),
Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
};

rsaProvider.ImportParameters(parameters);
return rsaProvider;
}

static X509Certificate2 GenerateCACertificate(string subjectName, ref


AsymmetricKeyParameter
By using our site, you acknowledgeCaPrivateKey)
that you have read and understand our Cookie Policy, Privacy Policy, and
{
our Terms of Service.
const int keyStrength = 2048;

https://stackoverflow.com/questions/11403333/httplistener-with-https-support 11/13
29/10/2019 .net - Httplistener with HTTPS support - Stack Overflow

// Generating Random Numbers


CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);

// The Certificate Generator


X509V3CertificateGenerator certificateGenerator = new
X509V3CertificateGenerator();

// 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);

// Issuer and Subject Name


X509Name subjectDN = new X509Name(subjectName);
X509Name issuerDN = subjectDN;
certificateGenerator.SetIssuerDN(issuerDN);
certificateGenerator.SetSubjectDN(subjectDN);

// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = notBefore.AddYears(2);

certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);

// Subject Public Key


AsymmetricCipherKeyPair subjectKeyPair;
KeyGenerationParameters keyGenerationParameters = new
KeyGenerationParameters(random, keyStrength);
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
subjectKeyPair = keyPairGenerator.GenerateKeyPair();

certificateGenerator.SetPublicKey(subjectKeyPair.Public);

// Generating the Certificate


AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

// 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;
}

static string GetLocalIPAddress()


{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
return "127.0.0.1";
//throw new Exception("No network adapters with an IPv4 address in the
system!");
}

static string ExecuteCommand(string action)


{
StringBuilder stringBuilder = new StringBuilder();
using (Process process = new Process
{
StartInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = "/c " + action
}
})
{
Console.WriteLine("Executing Command:");
Console.WriteLine(action);
process.Start();
while (!process.StandardOutput.EndOfStream)
{
stringBuilder.AppendLine(process.StandardOutput.ReadLine());
}
process.Close();
}

return stringBuilder.ToString();
}
}
}

answered Sep 28 at 18:59


Habib Sheikh
79 1 3

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

You might also like