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

时间:2008-08-06 21:18:47

标签: .net authentication encryption ssl

最近以粗体显示的修改 我正在使用.net HttpListener类,但我不会在IIS上运行而且不使用ASP.net。这个web site描述了用asp.net实现SSL的实际代码,this site描述了如何设置证书(虽然我不确定它是否只适用于IIS)。

类文档描述了各种类型的身份验证(基本,摘要,Windows等)---它们都没有引用SSL。它确实说如果HTTPS is used, you will need to set a server certificate。这将是一行属性设置,HttpListener计算其余部分吗?

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

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

  

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

编辑:
到目前为止采取的措施

  • 在C#中创建了一个适用于HTTP连接的工作HTTPListener(例如“http://localhost:8089/foldername/
  • 使用makecert.exe创建证书
  • 使用certmgr.exe
  • 添加了要信任的证书
  • 使用Httpcfg.exe侦听测试端口上的SSL连接(例如8090)
  • 通过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的前缀,这就是我所做的)
  • 错过了某个配置步骤?
  • 我还可以做些什么来分析问题?
  • 系统事件日志中的错误消息是否是问题的标志?如果是这样,它将如何修复?

6 个答案:

答案 0 :(得分:9)

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

这是适合我的路径:

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

然后查找证书thumbprint,将其复制到剪贴板并删除空格。这将是下一个命令中-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;

答案 1 :(得分:7)

您只需将证书绑定到ip:端口,然后使用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. 打开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();
    
  7. 运行此程序后,我只是导航到https://localhost:1234以查看打印的文本。由于证书CN与URL不匹配且它不在受信任证书存储中,因此您将获得证书警告。该文本已加密,但您可以使用Wire Shark等工具进行验证。

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


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

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

答案 2 :(得分:6)

我还没有完全实现它,但是这个网站似乎提供了good walkthrough设置证书和代码。

答案 3 :(得分: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。

答案 4 :(得分:3)

class documentation

有这个说明:

  

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

和此:

  

您可以配置服务器证书   和其他监听器选项   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将证书绑定到特定端口。如果他们想要除此之外的其他内容,则该注释含糊不清。

答案 5 :(得分:2)

我遇到了和你一样的问题。幸运的是,在this page上搜索硬步骤后,SSL使用了我的HttpListener。