.NET应用程序无法发送客户端证书 - Win 7 vs Win XP?

时间:2012-03-25 06:10:53

标签: .net client certificate ssl

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

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

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

我得到了我们最喜欢的例外,"无法创建SSL / TLS安全通道"。通常,这些类型的问题指出了证书的私钥权限问题。我尝试了所有我能想到的东西,以确保这一切都正确配置,但也许我错过了一些东西。简而言之,远程服务器正在发送一个TLS CertificateRequest,其列表似乎可以正确识别我的客户端证书,但我的应用程序无法响应任何客户端证书。

这是我的设置:

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

以下是我尝试的所有内容,以及我所知道的内容:

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

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

  

SecureChannel#26717201 - 我们有用户提供的证书。服务器指定了6个发行者。寻找与任何发行人匹配的证书。

     

SecureChannel#26717201 - 剩下0个客户端证书可供选择。

     

...

     

InitializeSecurityContext(In-Buffers count = 2,Out-Buffer length = 0,返回代码= CertUnknown)。

我已启用完整SCHANNEL logging,并看到此警告:

  

远程服务器已请求SSL客户端身份验证,但找不到合适的客户端证书。将尝试匿名连接。此SSL连接请求可能成功或失败,具体取决于服务器的策略设置。

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

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

任何想法都会非常感激。谢谢!

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

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

3 个答案:

答案 0 :(得分:8)

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

我能够使用我的代码成功地将请求发送到需要客户端证书的其他服务器。我在发送此成功请求时在Wireshark中捕获,并在将失败的请求发送到其他服务器时进行捕获。在Wireshark捕获中,我找到了“Server Hello”并比较了从远程服务器发送的消息。 “好的”远程服务器正在发送我的客户端证书,也在该消息的“证书请求”部分中发送其根证书。 “坏”远程服务器只发送了我的客户端证书。

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

答案 1 :(得分:7)

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

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

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

解决方案是要求服务器根本不发送列表。 (通过编辑注册表值)

HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \控制\ SecurityProviders \ SCHANNEL

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

答案 2 :(得分:0)

对我来说,这些确切的症状是由使用服务器不允许的TLS 1.0引起的。这可以在跟踪日志中找到:

  

System.Net信息:0:ProcessAuthentication(协议= Tls ,   密码= TripleDes 168位强度,Hash = Sha1 160位强度,密钥   交换= RsaKeyX 2048位强度)。

TLS 1.0是.NET 4.5的默认设置,但可以通过设置覆盖它:

ServicePointManager.SecurityProtocol = 
    SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

还有some registry flags允许在不更改现有代码的情况下进行设置。