X509Certificate2.Verify() method always return false for the valid certificate

后端 未结 2 448
渐次进展
渐次进展 2021-01-18 17:15

I am using smart card for authentication.

The SecurityTokenService (authentication service) is hosted on my machine only. The smart card has a valid certificate and

2条回答
  •  一向
    一向 (楼主)
    2021-01-18 18:01

    The X509VerificationFlags values are suppressions, so specifying X509VerificationFlags.AllFlags actually prevents Build from returning false in most situations.

    The RevocationStatusUnknown response seems particularly relevant. Whichever certificate it is reporting that for cannot be verified to be not revoked. The Verify method can be modeled as

    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);
        }
    }
    

    Which, since it is not asserting X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown or X509VerificationFlags.IgnoreEndRevocationUnknown while requesting an X509RevocationMode other than None, fails.

    First, you should identify which certificate(s) in the chain is(/are) failing:

    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}}}");
                }
            }
        }
    }
    

    If you look at any failing certificate in the Windows CertUI (double-click the .cer in Explorer or in the Certificates MMC Snap-In), look for a field named "CRL Distribution Points". These are the URLs that will be retrieved during runtime. Perhaps your system has a data egress restriction that doesn't allow those particular values to be queried for. You can always try issuing a web request from your web service to see if it can fetch the URLs without the context of being in the certificate subsystem.

提交回复
热议问题