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

pc1*_*ter 41 .net authentication encryption ssl

最新的粗体编辑 我使用.net HttpListener类,但我不会在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监听测试端口上的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的侦听器添加前缀,这就是我所做的)
  • 在某个地方错过了配置步骤?
  • 我还可以做些什么来分析问题?
  • 系统事件日志中的错误消息是否是问题的标志?如果是这样,它将如何修复?

gal*_*ets 10

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

这是对我有用的路径:

makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine
Run Code Online (Sandbox Code Playgroud)

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

HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755
Run Code Online (Sandbox Code Playgroud)

然后在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);
Run Code Online (Sandbox Code Playgroud)

证书显示正常,它有一个工作私钥,但https将超时,就像从未注册指纹一样.如果有人知道为什么 - 请注意

编辑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;
Run Code Online (Sandbox Code Playgroud)


Des*_*tar 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}
Run Code Online (Sandbox Code Playgroud)

如果要创建自签名证书来测试它,

  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();
    
    Run Code Online (Sandbox Code Playgroud)

运行此程序后,我只是导航https://localhost:1234到查看打印的文本.由于证书CN与URL不匹配且它不在受信任证书存储中,因此您将获得证书警告.该文本已加密,但您可以使用Wire Shark等工具进行验证.

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


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

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
Run Code Online (Sandbox Code Playgroud)


pc1*_*ter 6

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