如何将SSL添加到使用httplistener的.net应用程序 - 它不会*在IIS上运行

Most recent edits in bold I am using the .net HttpListener class, but I'm won't be running on IIS and am not using ASP.net. This web site describes what code to actual use to implement SSL with asp.net and this site describes how to set up the certificates (although I'm not sure if it works only for IIS or not).

类文档描述了各种类型的认证(基本,摘要,Windows等)---它们都不涉及SSL。它确实表示如果使用 HTTPS,您需要设置一个服务器证书。这将是一个单行属性设置,并且 HttpListener 会计算出其余的吗?

总之,我需要知道如何设置证书以及如何修改代码来实现SSL。

虽然在尝试访问HTTPS时不会发生,但我在系统事件日志中发现了一个错误 - 源是“Schannel”,消息的内容是:

尝试时发生致命错误   访问SSL服务器凭证   私钥。错误代码返回   来自加密模块   0x80090016。

Edit:
Steps taken so far

  • 在C#中创建一个可用于HTTP连接的工作HTTPListener(例如“ http:// localhost:8089 / foldername / / A>“
  • 使用makecert.exe创建证书
  • 使用certmgr.exe添加了要信任的证书
  • 使用Httpcfg.exe监听测试端口(例如8090)上的SSL连接
  • 通过listener.Prefixes.Add添加端口8080到HTTPListener。( https:// localhost:8090 / foldername / </一>“);
  • 测试了HTTP客户端连接,例如( http:// localhost:8089 / foldername / “),并收到正确的回复
  • 测试了HTTPS客户端连接,例如( http:// localhost:8090 / foldername / “),并收到”数据传输中断“(在Firefox中)
  • 在visual studio中进行调试显示,在HTTPS连接开始时,接收请求的侦听器回调从未被触发 - 我没有看到任何可以设置断点的位置来捕获其他任何内容。
  • netstat显示监听端口对于HTTPS和HTTP都是开放的。尝试连接后,HTTPS端口会转至TIME_WAIT。
  • 提琴手HTTPAnalyzer 不会捕获任何流量,我想这个流程没有足够远的地方显示在这些HTTP分析工具中

问题</强>

  • 问题是什么?
  • 是否存在一段我缺少的.Net代码(这意味着我必须在C#中执行更多操作,而不是简单地向指向HTTPS的侦听器添加前缀,这正是我所做的)
  • 错过某个配置步骤?
  • 我还可以做些什么来分析问题?
  • 系统事件日志中的错误消息是否是问题的标志?如果是的话,它将如何解决?
0

5 答案

我还没有完全实现它,但是这个网站似乎给了>良好的演练设置证书和代码。

0
额外

The class documentation

有这样的说明:

如果你使用创建一个HttpListener   https,你必须选择一个服务器   该听众的证书。   否则,请求一个HttpWebRequest查询   这个HttpListener会失败,并且会失败   意外关闭连接。

和这个:

您可以配置服务器证书   和其他侦听器选项   HttpCfg.exe。看到    http:// msdn .microsoft.com /库/ Default.asp的?URL = /库/ EN-US / HTTP / HTTP / httpcfg_exe.asp   更多细节。可执行文件是   随Windows Server 2003一起提供,或   可以从源代码构建   可以在Platform SDK中找到。

第二个解释的第一个音符是?如问题所述,我使用httpcfg.exe将证书绑定到特定端口。如果他们打算除此之外的其他东西,则说明不明确。

0
额外

您只需将证书绑定到ip:port,然后用https://前缀打开侦听器。 0.0.0.0适用于所有的IP。 appid是任何随机GUID,并且certhash是证书的散列(有时称为thumprint)。

使用管理员权限,使用cmd.exe运行以下内容。

netsh http add sslcert ipport=0.0.0.0:1234 certhash=613bb67c4acaab06def391680505bae2ced4053b  appid={86476d42-f4f3-48f5-9367-ff60f2ed2cdc}

如果你想创建一个自签名证书来测试这个,

  1. Open IIS
  2. Click on your computer name
  3. Click Server Certificates icon
  4. Click generate Self-Signed certificate
  5. Double click and go to details
  6. You will see the thumbprint there, just remove the spaces.

    HttpListener listener = new HttpListener();
    listener.Prefixes.Add("https://+:1234/");
    listener.Start();
    Console.WriteLine("Listening...");
    HttpListenerContext context = listener.GetContext();
    
    using (Stream stream = context.Response.OutputStream)
    using (StreamWriter writer = new StreamWriter(stream))
        writer.Write("hello, https world");
    
    Console.ReadLine();
    

运行此程序后,我只导航到 https:// localhost:1234 以查看打印的文本。由于证书CN与网址不匹配,并且它不在可信证书库中,您将收到证书警告。文本被加密,但您可以使用Wire Shark等工具进行验证。

如果您想要更多地控制创建自签名x509证书,openssl是一个很棒的工具,并且有一个用于Windows的端口。我比它的makecert工具有更多的成功。


同样非常重要的一点是,如果您从具有ssl警告的代码与https服务进行通信,则必须在服务点管理器上设置证书验证程序以绕过测试目的。

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
0
额外

我有类似的问题,似乎证书本身可能存在问题。

以下是适合我的路径:

makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine

然后查看证书指纹,将其复制到剪贴板并删除空格。这将是下一个命令中-h后的参数:

HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755

然后在 https:// localhost:801 / 上运行服务主机,并且它可以很好地工作。

我无法做的工作是让https运行在自行生成的证书上。这里是我运行的代码生成一个(错误处理为清晰起见):

LPCTSTR pszX500 = subject;
DWORD cbEncoded = 0;
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL);
pbEncoded = (BYTE *)malloc(cbEncoded);
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL);

// Prepare certificate Subject for self-signed certificate
CERT_NAME_BLOB SubjectIssuerBlob;
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob));
SubjectIssuerBlob.cbData = cbEncoded;
SubjectIssuerBlob.pbData = pbEncoded;

// Prepare key provider structure for self-signed certificate
CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("my-container");
KeyProvInfo.pwszProvName = NULL;
KeyProvInfo.dwProvType = PROV_RSA_FULL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_SIGNATURE;

// Prepare algorithm structure for self-signed certificate
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm));
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;

// Prepare Expiration date for self-signed certificate
SYSTEMTIME EndTime;
GetSystemTime(&EndTime);
EndTime.wYear += 5;

// Create self-signed certificate
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0);
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY");
CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0);

证书显示正常,并且它有一个可用的私钥,但https将超时,就好像指纹从未注册过一样。如果有人知道为什么 - PLZ评论

EDIT1: After some playing around, I have found the initialization for CertCreateSelfSignCertificate which generates proper certificate:

CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("my-container");
KeyProvInfo.pwszProvName = _T("Microsoft RSA SChannel Cryptographic Provider");
KeyProvInfo.dwProvType = PROV_RSA_SCHANNEL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
0
额外

这是另一种将SSL证书绑定到IP / PORT组合而不使用 httpcfg.exe (XP)或 netsh.exe (Vista +)的替代方法。

http://dotnetcodebox.blogspot.com .AU / 2012/01 /如何对工作与-SSL-certificate.html

它的要点是你可以使用C ++ HttpSetServiceConfiguration API内置在windows中,以编程方式执行,而不是通过命令行,从而消除了对操作系统的依赖并安装了httpcfg。

0
额外
我已经将此代码发布为 Nuget包。随意使用它。
额外 作者 Serghei Gorodetki,