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

Mik*_*ock 19 .net ssl client certificate

我正在开发一个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) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

这是我的设置:

  • 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 - 我们有用户提供的证书.服务器指定了6个发行者.寻找与任何发行人匹配的证书.

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

...

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

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

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

我运行了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中的受信任根,以便证书在我的计算机上显示为有效.这并没有解决问题.

Mik*_*ock 8

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

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

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

  • 你能帮忙澄清你为解决这个问题所做的工作吗?我正在使用自签名证书,只需使用以下内容验证证书:ServicePointManager.ServerCertificateValidationCallback = delegate(对象s,X509Certificate证书,X509Chain链,SslPolicyErrors sslPolicyErrors){return true; }; 我的主机已更新为.net 4.5,现在我的服务返回以下错误"无法创建SSL/TLS安全通道" (6认同)

小智 7

我想为问题添加另一个"解决方案".

如果该列表太长,服务器可能无法发送正确的颁发者列表.这似乎是微软的限制.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)