When building presentation software that requires secure internal communication, we face three unique constraints:
- Dynamic internal IPv4 addressing (typically in 192.168.0.x range)
- Potential IPv6-only environments
- No external certificate authority access (like Let's Encrypt)
- Zero manual configuration requirements
The most reliable solution is programmatic certificate generation during installation. Here's how to implement it in C#:
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
public X509Certificate2 CreateSelfSignedCertificate(string subjectName)
{
using (RSA rsa = RSA.Create(2048))
{
CertificateRequest req = new CertificateRequest(
$"CN={subjectName}",
rsa,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
req.CertificateExtensions.Add(
new X509KeyUsageExtension(
X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment,
false));
req.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") },
false));
req.CertificateExtensions.Add(
new X509BasicConstraintsExtension(false, false, 0, false));
return req.CreateSelfSigned(
DateTimeOffset.UtcNow.AddDays(-1),
DateTimeOffset.UtcNow.AddYears(1));
}
}
For HttpListener with PowerShell integration:
# PowerShell script to configure HTTPS binding
$cert = New-SelfSignedCertificate
-DnsName "internal-presentation.local"
-CertStoreLocation "cert:\LocalMachine\My"
-KeySpec KeyExchange
-KeyExportPolicy Exportable
$thumbprint = $cert.Thumbprint
$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert ipport=0.0.0.0:443
certhash=$thumbprint
appid=$guid
For IPv4/IPv6 agnostic operation:
// C# code to handle both IP versions
HttpListener listener = new HttpListener();
listener.Prefixes.Add("https://*:443/");
listener.Prefixes.Add("https://[::]:443/");
To avoid browser warnings without manual steps:
- Package the root CA with your installer
- Automate trust store installation
- Implement certificate pinning in your client code
// Certificate validation callback example
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, errors) =>
{
// Implement your custom validation logic here
return cert.Thumbprint == EXPECTED_THUMBPRINT;
};
- Set appropriate certificate expiration (1-2 years recommended)
- Implement automatic certificate renewal logic
- Include revocation checking for enterprise environments
- Consider using CNG instead of RSA for better performance
When developing presentation software that handles sensitive data like authentication tokens, enabling HTTPS is non-negotiable. However, internal networks present unique challenges:
- Dynamic IPv4 addresses (e.g., 192.168.0.x) and IPv6 configurations
- No public DNS resolution for Let's Encrypt validation
- Requirement for zero-touch deployment
For internal applications using HttpListener, self-signed certificates offer the most flexible approach. Here's how to implement this in C#:
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
class HttpsServer
{
static void Main()
{
var listener = new HttpListener();
listener.Prefixes.Add("https://localhost:8443/");
// Generate and install self-signed cert
var cert = CreateSelfSignedCertificate();
listener.Start();
Console.WriteLine("HTTPS server running...");
// Server logic here
}
static X509Certificate2 CreateSelfSignedCertificate()
{
var powershellScript = @"
$cert = New-SelfSignedCertificate -DnsName 'localhost' -CertStoreLocation 'cert:\LocalMachine\My'
Export-Certificate -Cert $cert -FilePath 'C:\temp\servercert.cer'
Import-Certificate -FilePath 'C:\temp\servercert.cer' -CertStoreLocation 'Cert:\LocalMachine\Root'
return $cert.Thumbprint
";
// Execute PowerShell and retrieve thumbprint
// Implementation omitted for brevity
return new X509Certificate2(/* cert data */);
}
}
For production environments, we need a fully automated solution. This PowerShell script handles certificate generation and binding:
# Generate self-signed certificate
$certParams = @{
Subject = "CN=YourInternalServer"
KeyAlgorithm = 'RSA'
KeyLength = 2048
NotBefore = Get-Date
NotAfter = (Get-Date).AddYears(5)
CertStoreLocation = 'Cert:\LocalMachine\My'
}
$cert = New-SelfSignedCertificate @certParams
# Export and import to Trusted Root
Export-Certificate -Cert $cert -FilePath "C:\Temp\InternalCert.cer"
Import-Certificate -FilePath "C:\Temp\InternalCert.cer" -CertStoreLocation 'Cert:\LocalMachine\Root'
# Configure HTTP.sys to use the certificate
netsh http add sslcert ipport=0.0.0.0:443 certhash=$($cert.Thumbprint) appid="{00112233-4455-6677-8899-AABBCCDDEEFF}"
For environments with dynamic internal IPs, consider these approaches:
- Use localhost binding with reverse proxy
- Implement internal DNS with static hostnames
- Leverage IPv6 link-local addresses which are more stable
Here's how to configure HttpListener for flexible addressing:
var listener = new HttpListener();
// Bind to all available addresses
listener.Prefixes.Add("https://+:443/");
listener.Prefixes.Add("https://[::]:443/"); // IPv6
While self-signed certificates solve the technical challenge, remember:
- Distribute the root CA certificate to all client machines
- Implement certificate pinning in your client software
- Rotate certificates periodically (automate this process)
For enterprise environments, consider setting up an internal PKI rather than individual self-signed certs.