NET应用程序未能发送客户端证书-Win 7 VS Win XP如何解决?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (27)

我正在开发一个ASP.NET Web应用程序,该应用程序使用HttpWebRequest向另一个服务器发送请求。它通过HTTPS发送请求,并且远程服务器需要客户端证书。该请求在.NET应用程序中失败,显然无法发送正确的客户端证书。我能够成功连接并发送客户端证书,如果我只需访问URL以网页浏览器(Chrome明确)。

下面的代码是一个简单的复制,只有一个基本的GET请求。

var r = WebRequest.Create(url) as HttpWebRequest;
r.ClientCertificates = new X509CertificateCollection { myX509Cert };
using (var resp = r.GetResponse() as HttpWebResponse) {
    ...
}

我得到我们最喜欢的例外,“无法创建SSL / TLS安全通道”。通常,这些类型的问题指出了证书私钥的权限问题。我尝试了所有我能想到的方法来确保所有配置都正确,但也许我错过了一些东西。长话短说,远程服务器正在发送一个CertificateRequest带有列表的TLS ,该列表似乎能够正确识别我的客户端证书,但是我的应用无法响应任何客户端证书。

这是我的设置:

  • Windows 7专业版64位
  • 能够在运行于Visual Studio开发服务器,在本地IIS中运行的ASP.NET WebForms / .NET 3.5应用程序以及在.NET控制台应用程序/ .NET 4中运行的ASP.NET MVC 3 / .NET 4应用程序中重现问题
  • 最近安装了Microsoft .NET Framework 4.5。还没有审查这是否可能是一个问题

这是我试过的一切,我知道的是:

  • 在Windows XP机器上运行时,此代码似乎工作正常
  • 我确保将我的客户端证书导入到本地计算机,个人证书存储中,并为我自己和所有相关的IIS用户正确配置了私钥权限
  • 我试图在我的机器上重新安装证书几次
  • 我已经确认.NET应用程序可以访问X509证书并且HasPrivateKey= true
  • 确保我的客户证书有效。它实际上是运行此应用程序的Web服务器的SSL证书
  • PreAuthenticate = true在请求对象中设置。没有区别
  • 我尝试设置ServicePointManager.Expect100Continue = false,没有什么区别
  • 我尝试设置ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3,但显然远程服务器需要TLS,所以这没有帮助
  • 我设置了一个ServicePointManager.ServerCertificateValidationCallback总是返回true 的委托。但是在TLS握手之前,请求失败了,甚至在它调用这个委托之前就失败了
  • 当我访问Chrome中的URL时,它会要求我提供客户端证书,提供正确的客户端证书作为选择,我选择该证书并获得有效的响应。当我在Fiddler中构造一个请求时也可以正常工作。所以这绝对是我的.NET代码特别是问题,而不是证书本身或远程服务器等。
  • 我正在使用的供应商在不同的远程服务器上设置了相同的服务,并且该服务需要不同的客户端证书。所以我尝试了不同的URL和客户端证书,并得到了同样的失败

我添加了System.Net跟踪并看到了这一点:

SecureChannel#26717201 - We have user-provided certificates. The server has specified 6 issuer(s). Looking for certificates that match any of the issuers.

SecureChannel#26717201 - Left with 0 client certificates to choose from.

...

InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CertUnknown).

我启用了完整的SCHANNEL日志记录,并看到此警告:

The remote server has requested SSL client authentication, but no suitable client certificate could be found. An anonymous connection will be attempted. This SSL connection request may succeed or fail, depending on the server's policy settings.

我运行了Wireshark,并看到远程服务器发送了一个CertificateRequest,并且它似乎有一个Distinguished Name条目,其中指定了我的客户端证书的CN \ OU \ O值。之后,我的应用程序发送一个证书响应,没有证书。

似乎我错过了设置此证书以便在Windows 7中与.NET应用程序一起正常工作的情况。我最好的猜测是,与XP计算机相比,我的新Windows 7计算机上有一些不同的东西导致了这种情况现在失败。我目前无法访问Windows XP环境来确认这一点; 我会在几天内,但真的想尽快解决这个问题。

如上所述,当在Chrome中连接到URL时,浏览器要求我提供客户端证书,并且我可以提供正确的证书并成功连接。但是,我无法在Internet Explorer(9)中成功完成此操作。我只是得到“Internet Explorer无法显示网页”,没有其他提示或解释。我被告知这可能WebRequest.Create与IE有类似的行为有关。我正在研究这可能意味着什么,但会重视对此的任何想法。

另外,我应该注意到远程服务器使用自签名的SSL证书。我原本以为这可能是问题所在,因此我将该证书添加为MMC中的受信任根,以便证书在我的计算机上显示为有效。这并没有解决问题。

提问于
用户回答回答于

原来这是一个相当简单的问题,但很难发现。我的应用程序在其密钥库中有我的客户端证书的远程服务器,但不是我客户端证书的信任链中的任何根证书。

我能够使用我的代码成功发送请求到需要客户端证书的不同服务器。在发送这个成功的请求时,我在Wireshark中捕获了一个捕获,并在发送失败请求到另一个服务器时进行了捕获。在Wireshark捕获中,我找到了“Server Hello”并比较了从远程服务器发送的消息。“良好”的远程服务器正在发送我的客户端证书,并且还在其消息的“证书请求”部分发送其根证书。“不好”的远程服务器只发送我的客户端证书。

这提醒我System.Net诊断跟踪读取“服务器已指定6个发行者...留下0个客户端证书可供选择”。所以事实证明,“发行人”是这里的关键词。最初很容易忽略,因为在我对TLS握手的初步分析中,服务器在证书请求中发送了我的客户端证书。事后看来,服务器应该发送根证书而不是客户端证书本身是有道理的。

用户回答回答于

我想为这个问题增加另一个“解决方案”。

如果该列表太长,服务器可能无法发送正确的发布者列表。这似乎是微软的限制。http://support.microsoft.com/kb/933430

资料来源:http : //netsekure.org/2011/04/tls-client-authentication-and-trusted-issuers-list/

解决办法是要求服务器不要发送列表。(通过编辑注册表值)

HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \控制\ SecurityProviders \ SCHANNEL

值名称:SendTrustedIssuerList值类型:REG_DWORD值数据:0(False)

扫码关注云+社区