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

最近的粗体编辑我使用.net HttpListener类,但我不会在IIS上运行,而不是使用ASP.net。 这个网站描述了实际使用什么代码来实现与asp.net的SSL, 这个网站描述了如何设置证书(虽然我不知道它是否只适用于IIS)。

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

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

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

尝试访问SSL服务器凭证私钥时发生致命错误。 从encryption模块返回的错误代码是0x80090016。

编辑:
迄今采取的步骤

  • 在C#中创build一个可用于HTTP连接的工作HTTPListener(例如“ http:// localhost:8089 / foldername / ”
  • 使用makecert.exe创build一个证书
  • 使用certmgr.exe添加了要信任的证书
  • 使用Httpcfg.exe来侦听testing端口上的SSL连接(例如8090)
  • 通过listener.Prefixes.Add( https:// localhost:8090 / foldername / “)将端口8080添加到HTTPListener中。
  • 在浏览器中testingHTTP客户端连接,例如( http:// localhost:8089 / foldername / ),并接收正确的返回
  • 在浏览器中testing了HTTPS客户端连接,例如( http:// localhost:8090 / foldername / ),并接收到“数据传输中断”(在Firefox中)
  • 在Visual Studio中进行debugging显示,当HTTPS连接开始时,接收请求的侦听器callback不会被触发 – 我没有看到任何可以设置断点的位置来捕捉其他事情。
  • netstat显示侦听端口对于HTTPS和HTTP都是开放的。 在尝试连接后,HTTPS端口将转至TIME_WAIT。
  • 提琴手和HTTPAnalyzer不捕捉任何stream量,我想它没有得到足够的过程中显示在这些HTTP分析工具

问题

  • 问题是什么?
  • 是否有一段.net代码我错过了(这意味着我必须在C#中做更多的事情,而不是简单地添加一个前缀到指向HTTPS的侦听器,这是我所做的)
  • 有没有错过configuration步骤?
  • 我还可以做些什么来分析问题?
  • 系统事件日志中的错误消息是问题的标志? 如果是这样如何解决?

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

这是我工作的道路:

 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运行在自己生成的证书上。 这里是我运行的代码生成一个(清除error handling):

 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评论

编辑1 :一些玩过之后,我发现了CertCreateSelfSignCertificate的初始化,它会生成适当的证书:

 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; 

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

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

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

如果你想创build一个自签名证书来testing这个,

  1. 打开IIS
  2. 点击你的电脑名称
  3. 单击服务器证书图标
  4. 点击生成自签名证书
  5. 双击并进入细节
  6. 你会看到那里的指纹,只是删除空格。

     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与url不匹配,并且不在可信证书库中,您将收到证书警告。 文本被encryption,但你可以使用像Wire Shark这样的工具进行validation。

如果你想更多的控制创build一个自签名的x509证书openssl是一个伟大的工具,并有一个Windows的端口。 我比makecert工具有更多的成功。


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

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

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

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

http://dotnetcodebox.blogspot.com.au/2012/01/how-to-work-with-ssl-certificate.html

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

类文档

有这个说明:

如果使用https创buildHttpListener,则必须为该侦听器select一个服务器证书。 否则,此HttpListener的HttpWebRequest查询将失败,并意外closures连接。

和这个:

您可以使用HttpCfg.execonfiguration服务器证书和其他侦听器选项。 有关更多详细信息,请参阅http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp 。 可执行文件随Windows Server 2003一起提供,或者可以从Platform SDK中提供的源代码构build。

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

我遇到了和你一样的问题。 幸运的是,在这个页面上用Googlesearch艰难的步骤后,SSL使用我的HttpListener。