建立SSL/TLS连接(X509Chain.Build())需要太长时间。

8

我发现当我使用HttpWebRequest来建立SSL\TLS连接时,调用时需要近30秒的时间

  request.GetRequestStream()

当我启用了带有堆栈跟踪的跟踪功能时,我发现寻找代理需要2秒钟的时间,因此我在app.config中禁用了它:

<system.net>
 <defaultProxy enabled="false" useDefaultCredentials="false">
  <proxy/>
  <bypasslist/>
  <module/>
 </defaultProxy>
</system.net>

下一个点在大约28秒内到达

   at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)

在检查方法体之后,我发现调用了X509Chain.Build()方法,并且建立证书链花费了将近25秒。

有趣的是,当您构造新的HttpWebReqest并再次尝试(无需重新启动应用程序),执行请求只需要几毫秒。

有人能提供建议吗?缓存请求不是一个选项,必须从应用程序运行时开始就很快。

更新:

我发现在X509Chain.BuildChain()中需要30秒的调用是:

if (!CAPISafe.CertGetCertificateChain(hChainEngine, pCertContext, ref pTime, invalidHandle, ref cert_chain_para, dwFlags, IntPtr.Zero, ref ppChainContext))

CAPISafe中声明的方法如下:
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool CertGetCertificateChain([In] IntPtr hChainEngine, [In] SafeCertContextHandle pCertContext, [In] ref System.Runtime.InteropServices.ComTypes.FILETIME pTime, [In] SafeCertStoreHandle hAdditionalStore, [In] ref CAPIBase.CERT_CHAIN_PARA pChainPara, [In] uint dwFlags, [In] IntPtr pvReserved, [In, Out] ref SafeCertChainHandle ppChainContext);

所以,这是加密API函数CertGetCertificateChain。仍然不知道下一步该怎么做...
更新:
我尝试禁用CRL和OCSP检查,但仍然没有效果:
  1. Add to App.config

    <runtime>
      <generatePublisherEvidence enabled="false"/>
    </runtime>
    
  2. Machine-wide: Control Panel -> Internet Options -> Advanced -> Under security, uncheck the Check for publisher's certificate revocation option

  3. In registry:

    [HKEY_USERS\S-1-5-20\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing] "State"=dword:00023e00


就此而言,#1会根据应用程序的Authenticode签名关闭证据生成,如果有的话。#2关闭Authenticode吊销检查以进行Authenticode签名(仅在极少数情况下使用)。这两者都不适用于SSL客户端证书吊销检查。 - EricLaw
2个回答

8

微软的其中一位开发人员也有过一篇相关的博客文章: https://blogs.msdn.microsoft.com/alejacma/2011/09/27/big-delay-when-calling-sslstream-authenticateasclient/ - Aidin

4
通常,路径构建意味着构建一个有效的路径,这需要检查是否有任何证书自颁发以来已被吊销。为了检查当前的吊销状态,您需要来自CRL或OCSP响应者的最新信息。如果在路径验证请求的设置期间未显式提供正确的CRL,则许多库将尝试获取它(通常通过Internet),如果CRL的URL在“CRL分发点”扩展中列出,则会尝试获取它。如果您的网络速度较慢,路径较长或CRL较大,则这可能需要一些时间。也许这就是您的情况所花费的时间。由于第一次运行后速度很快,我猜测在第一次尝试期间下载了一些大型CRL,并缓存以供后续使用。
或者,如果在“颁发者信息访问”扩展中广告了OCSP响应者,则该库可能会自动联系OCSP响应者。但是,某些库需要明确配置才能使用OCSP或优先使用它而不是CRL。如果您正在验证每个不同颁发者的少量证书,请尽可能使用OCSP。该协议速度快,响应很小,通常仅包含关于单个证书的信息,而不是颁发者曾吊销的每个证书的信息。
如果您正在验证来自单个颁发者的许多证书,请在后台急切地下载该颁发者的CRL,并保留直到其过期。然后将CRL传递到路径构建过程中,以便在用户等待时无需下载它。

谢谢您的回复。从代码中可以看出,似乎这不是一个选项,因为X509Chain实例是这样创建的: c X509Chain chain = new X509Chain { ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck, VerificationFlags = X509VerificationFlags.IgnoreInvalidName } };此外,证书具有空的OCSP列表。 - hkurabko
现在,我发现即使禁用了CRL和OCSP检查,应用程序仍然尝试连接到这些IP地址:8.26.222.254:http 199.93.57.254:http 206.33.54.126:http 4.26.235.254:http 8.27.7.126:http所以,也许你是对的。但它应该在哪里禁用?而且,禁用它真的是一个好理由吗? - hkurabko
已检查。证书链中没有CRL分发点,也没有任何OCSP在列表中的证书。因此,问题是,它连接到哪里和为什么连接? - hkurabko
@hkurabko 奇怪。这些都是Level 3内容交付网络中的服务器。这些连接速度慢吗?您能否使用WireShark或其他工具观察请求,以找出它们的性能如何?此外,通常不应禁用撤销检查。但是,关闭它们以尝试隔离问题是一个好的举措。 - erickson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接