【问题标题】:X509Certificate2.Verify() method always return false for the valid certificateX509Certificate2.Verify() 方法始终为有效证书返回 false
【发布时间】:2012-04-13 08:00:13
【问题描述】:

我正在使用智能卡进行身份验证。

SecurityTokenService(身份验证服务)仅托管在我的机器上。智能卡有一个有效的证书,它的根证书也安装在我机器上的本地计算机存储中。

当我使用X509Certificate2.Verify 方法在我的服务中验证证书时,它总是返回false

谁能帮我理解为什么 X509Certificate2.Verify() 方法总是返回 false?

注意: 我使用了X509Chain 并检查了所有标志(X509VerificationFlags.AllFlags)。当我构建 chanin 时,它返回 trueChainStatus 作为 RevocationStatusUnknown


编辑 1:

我观察到如果我在 Windows 窗体应用程序中编写此代码,X509Certificate2.Verify() 方法将返回 true。它仅在服务端代码中返回 false。为什么这样?奇怪但真实!

【问题讨论】:

    标签: c# x509certificate2


    【解决方案1】:

    X509VerificationFlags 值是抑制值,因此指定 X509VerificationFlags.AllFlags 实际上会阻止 Build 在大多数情况下返回 false。

    RevocationStatusUnknown 响应似乎特别相关。无论它报告的哪个证书都无法验证为未被撤销。 Verify 方法可以建模为

    public bool Verify()
    {
        using (X509Chain chain = new X509Chain())
        {
            // The defaults, but expressing it here for clarity
            chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
            chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
            chain.ChainPolicy.VerificationTime = DateTime.Now;
            chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
    
            return chain.Build(this);
        }
    }
    

    由于它在请求 None 以外的 X509RevocationMode 时未断言 X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknownX509VerificationFlags.IgnoreEndRevocationUnknown,因此失败。

    首先,您应该确定链中的哪些证书(/正在)失败:

    using (X509Chain chain = new X509Chain())
    {
        // The defaults, but expressing it here for clarity
        chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
        chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
        chain.ChainPolicy.VerificationTime = DateTime.Now;
    
        chain.Build(cert);
    
        for (int i = 0; i < chain.ChainElements.Count; i++)
        {
            X509ChainElement element = chain.ChainElements[i];
    
            if (element.ChainElementStatus.Length != 0)
            {
                Console.WriteLine($"Error at depth {i}: {element.Certificate.Subject}");
    
                foreach (var status in element.ChainElementStatus)
                {
                    Console.WriteLine($"  {status.Status}: {status.StatusInformation}}}");
                }
            }
        }
    }
    

    如果您在 Windows CertUI 中查看任何失败的证书(在资源管理器或证书 MMC 管理单元中双击 .cer),请查找名为“CRL 分发点”的字段。这些是将在运行时检索的 URL。也许您的系统有一个数据出口限制,不允许查询这些特定值。您始终可以尝试从您的 Web 服务发出 Web 请求,以查看它是否可以在没有位于证书子系统中的上下文的情况下获取 URL。

    【讨论】:

      【解决方案2】:

      我认为,问题是由于我的组织中的代理服务器和一些安全设置造成的。我无法给出为什么它可以在 WinForm 客户端运行以及为什么不能从 IIS 下托管的代码中运行的正当理由。

      但我想让读者知道的事实是,当我在 IIS 中托管服务时,Verify() 方法也适用于服务器端代码,该服务在我常用域之外的机器上运行!因此,您可以检查您的域/组织的防火墙设置是否妨碍您。

      【讨论】:

      • WinForm 客户端将在您的域凭据下工作,而在 IIS 中,凭据会有所不同。可能这可能是原因之一。尝试在 IIS 中启用 Windows 身份验证,看看是否有任何不同。
      • Web 应用程序在NETWORK SERVICE 帐户下运行。该用户有权访问证书。但是,是的,您的观点是正确的;这通常是 IIS Web 应用程序中的 Verify() 方法失败的原因。
      猜你喜欢
      • 2019-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      • 2012-08-27
      • 2019-05-25
      • 2011-11-30
      • 1970-01-01
      相关资源
      最近更新 更多