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

最后都变了- 提交于 2019-12-01 19:41: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 it's root certificate is also installed in Local Computer store on my machine.

When I use X509Certificate2.Verify method to validate the certificate in my service, it always return false.

Can someone help me to understand why X509Certificate2.Verify() method always return false?

Note: I used X509Chain and checked for all the flags (X509VerificationFlags.AllFlags). When I build the chanin, it returns true with ChainStatus as RevocationStatusUnknown.


EDIT 1:

I observed that X509Certificate2.Verify() method returns true if i write this code in windows form application. It returns false only in the service side code. Why so? Strange but true!


回答1:


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.




回答2:


I think, the problem is due to the proxy server and some security settings in my organization. I cannot give valid reason why it works from WinForm client and why does not from code hosted under IIS.

But the fact I want to let readers know is that Verify() method worked on server side code too when I hosted service in IIS running on the machine outside my usual domain! So you may check if the firewall settings of your domain/organization is coming in you way.



来源:https://stackoverflow.com/questions/10137208/x509certificate2-verify-method-always-return-false-for-the-valid-certificate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!