43

最近的粗体编辑 我正在使用 .netHttpListener类,但我不会在 IIS 上运行此应用程序,也不会使用 ASP.net。这个网站描述了实际使用什么代码来实现与 asp.net 的 SSL,并且这个网站描述了如何设置证书(虽然我不确定它是否只适用于 IIS)。

类文档描述了各种类型的身份验证(基本、摘要、Windows 等)——它们都没有提到 SSL。它确实说如果使用 HTTPS,则需要设置服务器证书。这将是一个单行属性设置并HttpListener计算其余部分吗?

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

虽然在我尝试访问 HTTPS 时没有发生这种情况,但我确实注意到我的系统事件日志中有一个错误 - 源是“Schannel”,消息的内容是:

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

编辑:
到目前为止采取的步骤

  • 在 C# 中创建了一个适用于 HTTP 连接的有效 HTTPListener(例如“ http://localhost:8089/foldername/
  • 使用 makecert.exe 创建证书
  • 使用 certmgr.exe 添加了要信任的证书
  • 使用 Httpcfg.exe 监听测试端口(例如 8090)上的 SSL 连接
  • 通过 listener.Prefixes.Add( https://localhost:8090/foldername/ ")将端口 8080 添加到 HTTPListener ;
  • 在浏览器中测试 HTTP 客户端连接,例如 ( http://localhost:8089/foldername/ ") 并收到正确的返回
  • 在浏览器中测试了一个 HTTPS 客户端连接,例如(http://localhost:8090/foldername/)并收到“数据传输中断”(在 Firefox 中)
  • Visual Studio 中的调试表明,当 HTTPS 连接启动时,接收请求的侦听器回调永远不会被命中 - 我看不到任何可以设置断点以更早捕获其他内容的地方。
  • netstat 显示监听端口对 HTTPS 和 HTTP 都是开放的。尝试连接后,HTTPS 端口确实会进入 TIME_WAIT。
  • FiddlerHTTPAnalyzer没有捕捉到任何流量,我猜它在这个过程中还远远不够显示在那些 HTTP 分析工具中

问题

  • 问题可能是什么?
  • 是否有一段.Net 代码我丢失了(这意味着我必须在 C# 中做更多事情,而不是简单地向指向 HTTPS 的侦听器添加一个前缀,这就是我所做的)
  • 在某处错过了配置步骤?
  • 我还能做些什么来分析问题?
  • 系统事件日志中的错误消息是否表明存在问题?如果是这样,它将如何修复?
4

6 回答 6

10

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

这是对我有用的路径:

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 将超时,就好像从未注册过指纹一样。如果有人知道为什么 - 请评论

EDIT1:经过一番玩耍,我找到了 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;
于 2009-04-07T21:15:40.927 回答
6

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

使用管理员权限使用 cmd.exe 运行以下命令。

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

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

  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 不匹配并且它不在受信任的证书存储中,您将收到证书警告。然而,文本是加密的,因为您可以使用 Wire Shark 等工具进行验证。

如果您想更好地控制创建自签名 x509 证书,openssl 是一个很棒的工具,并且有一个适用于 windows 的端口。与 makecert 工具相比,我在它方面取得了更大的成功。


如果您从带有 ssl 警告的代码与 https 服务进行通信,您必须在服务点管理器上设置证书验证器以绕过它以进行测试,这一点也非常重要。

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
于 2012-09-29T03:55:20.257 回答
5

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

于 2008-08-06T22:29:57.073 回答
4

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

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

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

于 2015-03-02T05:14:45.000 回答
3

文档

有这个注释:

如果使用 https 创建 HttpListener,则必须为该侦听器选择服务器证书。否则,此 HttpListener 的 HttpWebRequest 查询将因连接意外关闭而失败。

和这个:

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

第一个注释是否由第二个注释解释?如问题中所述,我使用 httpcfg.exe 将证书绑定到特定端口。如果他们打算除此之外的其他内容,则说明是模棱两可的。

于 2008-08-08T16:37:29.820 回答
2

我遇到了和你一样的问题。幸运的是,在此页面上搜索了艰难的步骤后,SSL 可以与我的 HttpListener 一起使用。

于 2009-01-28T10:22:57.570 回答