支持HTTPS的Httplistener

时间:2012-07-09 21:19:38

标签: .net x509certificate httplistener

对于支持.NET HTTPListener HTTPS,似乎有很多令人困惑的,有时是冲突的信息。我的理解如下:

  • 一个人的C#代码需要一个https前缀(例如,https://*:8443),以便侦听器了解它需要在此端口处为SSL请求提供服务。

    < / LI>
  • 实际的SSL握手发生在幕后,由http.sys处理(埋在Windows机器的某处)。 C#代码不必显式管理SSL握手,因为它发生在幕后。

  • 需要在httpListener计算机上拥有“X.509可信证书”,并且该证书需要以某种方式绑定到端口8443(在此示例中)。

我的理解是否正确?如果没有,请教育我。

关于X.509证书,我的理解是:

  • 使用makecert创建X.509证书。此证书存储在个人存储中,需要转移到可信存储(这是HTTP侦听器所在的位置)。我似乎可以使用certMgr来执行移动,或者我可以使用mmc来实现移动。似乎有多种X.509证书格式(DERBase64pks,pswd受保护,pks私有等等。)...是否有我应该使用的首选格式?

一旦我将证书送入可信商店,我需要将其绑定到TCP端口。我在Windows 7上:我应该使用httpcfg还是netsh

5 个答案:

答案 0 :(得分:76)

我做了一大堆功课,让这个工作。为.NET HttpListener添加SSL支持的步骤是:

  1. 更新C#应用程序代码以包含https前缀。例如:

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

    从代码方面来看就是这样。

  2. 对于证书方面的事情,使用Windows SDK命令控制台(也可以使用Visual Studio Professional命令控制台)

    • 使用makecert.exe创建证书颁发机构。例如:

      makecert -n "CN=vMargeCA" -r -sv vMargeCA.pvk vMargeCA.cer
      
    • 使用makecert.exe创建SSL证书

        

      makecert -sk vMargeSignedByCA -iv vMargeCA.pvk -n "CN=vMargeSignedByCA" -ic vMargeCA.cer vMargeSignedByCA.cer -sr localmachine -ss My

    • 使用MMC GUI在Trusted Authority store中安装CA

    • 使用MMC GUI在个人存储中安装SSL证书
    • 将证书绑定到IP address:port和应用程序。例如:

        

      netsh http add sslcert ipport=0.0.0.0:8443 certhash=585947f104b5bce53239f02d1c6fed06832f47dc appid={df8c8073-5a4b-4810-b469-5975a9c95230}

      certhash是SSL证书的指纹。你可以用mmc找到它。 appid可以在Visual Studio中找到...通常在assembly.cs中,查找GUID值。

  3. 可能还有其他方法可以实现上述目标,但这对我有用。

答案 1 :(得分:28)

以下是我在Windows上设置独立服务器时所遵循的步骤,使用OpenSSL为C#HTTPListener应用程序创建自签名证书。如果您想进一步研究,它包含大量链接。

  1. 通过HttpListener

    在.NET中创建独立服务器
    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();
    
  2. 创建自签名证书: *

    1. openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365,它将提示您输入命令行中每个证书字段的值。对于公用名,请键入域名(例如localhost
    2. openssl pkcs12 -inkey bob_key.pem -in bob_cert.cert -export -out bob_pfx.pfx,以便可以使用其键在目标计算机上导入。
    3. * 对于使用makecert的替代方案,请参阅Walter自己的answer

    4. 打开本地计算机的证书管理器。当您运行certmgr.msc时,它会打开当前用户的证书管理器,这不是我们想要的。代替:

      1. 从目标计算机上的管理命令提示符处运行mmc
      2. Ctrl + M ,或点击 文件&gt; 添加/删除管理单元
      3. 选择Certificates,然后点击添加&gt;
      4. 在显示的对话框中,选择Computer Account,然后点击下一步
      5. 选择Local Computer。单击完成,然后 Okay
    5. 将证书(pfx)导入目标计算机上的Windows Certificate Store

      1. 在之前打开的mmc窗口中,深入查看 证书(本地计算机)&gt; 个人
      2. 右键点击Personal,然后点击 所有任务 - &gt; 导入...
      3. 在出现的对话框的第二个屏幕中,查找并导入您的证书。您必须将文件类型过滤器更改为Personal Information ExchangeAll Files才能找到它
      4. 在下一个屏幕上,输入您在步骤2.1中选择的密码,并密切注意第一个复选框。这决定了您的证书的存储安全性,以及使用它的方便程度
      5. 在最后一个屏幕上,选择Place all certificates in the following store。验证它是否显示Personal,然后单击完成
      6. Trusted Root Certification Authorities证书部分重复上述导入过程。
    6. 为您的应用程序创建端口关联。在Windows Vista及更高版本中,像我一样使用netsh。 (对于Windows XP及更早版本,请使用httpcfg

      • 在管理命令行中,键入以下内容以将SSL binding * 设置为您的应用以及相应的端口。 NB:此命令为easy to get wrong,因为(在PowerShell中)大括号需要为escaped。以下PowerShell命令将起作用:

        netsh http add sslcert ipport=0.0.0.0:8443 `
            certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 `
            appid=`{00112233-4455-6677-8899-AABBCCDDEEFF`}
        

        对于cmd.exe,应使用以下内容:

        netsh http add sslcert ipport=0.0.0.0:8443 certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
        
        • ipport参数将导致SSL证书绑定到每个网络接口上的端口8443;要绑定到特定接口(仅限),请选择与该网络接口关联的IP地址。
        • certhash只是证书指纹,删除了空格
        • appid是存储在应用程序的程序集信息中的GUID。 (旁注:netsh机制显然是一个COM界面,从question及其答案来判断)

        * Microsoft已将 SSL Binding 链接从here重定向到there

    7. 启动您的网络服务器,您就可以开始了!

答案 2 :(得分:1)

由于在答案中制作自己的自签名证书对我不起作用,因为问题特别要求使.net HTTPListener https能够并且要求任何提示/建议,我想分享我的方法。你需要一个主机名,例如www.made-up.com,需要指向您的WAN IP(例如询问您的主机提供商的说明)并转发其端口,例如443到您的本地机器。不要忘记在本地机器的防火墙中打开入站443端口。

我使用了https://letsencrypt.org/。在Windows上,这并不像在Linux上那么容易,因为Windows没有官方的certbot ACME客户端。但是你可以使用https://github.com/Lone-Coder/letsencrypt-win-simple,其中也有二进制文件。但是&#34;目前只支持IIS&#34;。但您可以轻松欺骗它在您的计算机上创建证书,以便您可以通过SSL方式访问您的httplistener:

  1. 安装IIS(通过/上的Windows功能),在IIS中创建一个网站并分配主机名。还可以建立一个安全的(443端口)网站。
  2. 运行letsencrypt-win-simple exe(我使用的是1.9.1版本)。回答问题,让它生成证书。
  3. 之后,您可以停止de IIS服务器。
  4. 我相信您必须注意生成的刷新任务,因为我不确定它会在几个月后成功(您可能必须再次启动IIS才能续订证书)。

答案 3 :(得分:0)

我们可以使用PowerShell和C#导入证书(无需手动步骤)。

有关详细信息,请参见:https://blog.davidchristiansen.com/2016/09/howto-create-self-signed-certificates-with-powershell/

我正在使用以下代码:

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

        // This adds certificate to Personal and Intermediate Certification Authority
        var rootAuthorityName = "My-RootAuthority";
        var rootFriendlyName = "My Root Authority";
        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();
    }
}

需要PowerShell 4或更高版本。

答案 4 :(得分:-1)

以下命令为本地主机生成十年的自签名证书,将其导入本地计算机存储,并在输出中显示Thumbprint(certhash):

powershell -Command "New-SelfSignedCertificate -DnsName localhost -CertStoreLocation cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(10)"

然后,您可以从输出中复制Thumbprint,然后使用netsh.exe将证书附加到localhost:443,例如:

netsh http add sslcert ipport=localhost:443 certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}

可在Windows 8或更高版本上使用。需要管理员权限。